今日题目有:
- 数组中重复的数据
- 合并K个升序链表
1. 数组中重复的数据
题目描述
给你一个长度为 n 的整数数组 nums ,其中 nums 的所有整数都在范围 [1, n] 内,且每个整数出现 最多两次 。请你找出所有出现 两次 的整数,并以数组形式返回。
你必须设计并实现一个时间复杂度为 O(n) 且仅使用常量额外空间(不包括存储输出所需的空间)的算法解决此问题。
示例:
输入:nums = [4,3,2,7,8,2,3,1]
输出:[2,3]
思路
- 原地哈希 合理利用所有数字都在1~n这个范围,可以把每个数都当成是一个索引,我们把当前索引的值标记为负数,计作已访问。当逐个标记时遇到负数,则说明重复。
- 转换成位图 这里最多有100000个数,那么对于一个64位的数来说,我们需要差不多100063/64 = 1563个单元来存。每个数字都可以对应位图中的某一位。 然后遍历原数组,看对应位是否访问过即可。
Swift实现
// solution1
func findDuplicates(_ nums: [Int]) -> [Int] {
var ans = [Int](), numsCopy = nums
guard nums.count > 0 else { return ans }
let len = nums.count
for num in numsCopy {
let curNum = abs(num)
if numsCopy[curNum - 1] > 0 {
numsCopy[curNum - 1] = -numsCopy[curNum - 1]
} else {
ans.append(curNum)
}
}
return ans
}
// solution2
func findDuplicates(_ nums: [Int]) -> [Int] {
var idxs = Array(repeating: UInt(0), count: 100063 / 64)
// 转成位图,idxs[i] 负责 存储 i × 64 到 (i+1) × 64 - 1 这 64 个数字的状态。
var total: [Int] = []
for num in nums {
let i = (num) / 64
let idx: UInt
if i > 0 {
// 移位 idx表示当前数字对应2进制数
idx = (1 << ((num) % 64))
} else {
idx = (1 << ((num) % 64 - 1))
}
if idxs[i] & idx > 0 {
// 对应位数是1,说明出现过,重复。
total.append(num)
} else {
// 把对应位置标记成1
idxs[i] |= idx
}
}
return total
}
2. 合并K个升序链表
题目描述
给你一个链表数组,每个链表都已经按升序排列。
请你将所有链表合并到一个升序链表中,返回合并后的链表。
示例:
输入:lists = [[1,4,5],[1,3,4],[2,6]]
输出:[1,1,2,3,4,4,5,6]
解释:链表数组如下:
[
1->4->5,
1->3->4,
2->6
]
将它们合并到一个有序链表中得到。
1->1->2->3->4->4->5->6
思路
比较容易想到的一个方法就是分治,先两两合并,最终合成一个大的。
Swift实现
func mergeKLists(_ lists: [ListNode?]) -> ListNode? {
if lists.count == 0 {
return nil
}
if lists.count == 1 {
return lists[0]
}
let mid = lists.count/2
let left = mergeKLists(Array(lists[0..<mid]))
let right = mergeKLists(Array(lists[mid..<lists.count]))
return mergeTwoLists(left, right)
}
func mergeTwoLists(_ first: ListNode?, _ second: ListNode?) -> ListNode? {
var firstNode = first, secondNode = second
let head = ListNode.init(-1)
var current:ListNode? = head
while firstNode != nil && secondNode != nil{
if firstNode?.val ?? 0 < secondNode?.val ?? 0{
current?.next = firstNode
firstNode = firstNode?.next
current = current?.next
} else {
current?.next = secondNode
secondNode = secondNode?.next
current = current?.next
}
}
if firstNode != nil {
current?.next = firstNode
} else if secondNode != nil {
current?.next = secondNode
}
return head.next
}
...