面试题 17.19. 消失的两个数字
给定一个数组,包含从 1 到 N 所有的整数,但其中缺了两个数字。你能在 O(N) 时间内只用 O(1) 的空间找到它们吗?
以任意顺序返回这两个数字均可。
示例 1:
输入: [1]
输出: [2,3]
示例 2:
输入: [2,3]
输出: [1,4]
提示:
nums.length <= 30000
思路:
这道题我感觉和41.缺失的第一个正数很像。这题是找出两个,那题是找出一个。
套用一下大佬的题解:
方法三:将数组视为哈希表
最早知道这个思路是在《剑指 Offe》这本书上看到的,感兴趣的朋友不妨做一下这道问题:剑指 Offer 03. 数组中重复的数字。下面简要叙述:
由于题目要求我们「只能使用常数级别的空间」,而要找的数一定在 [1, N + 1] 左闭右闭(这里 N 是数组的长度)这个区间里。因此,我们可以就把原始的数组当做哈希表来使用。事实上,哈希表其实本身也是一个数组;
我们要找的数就在 [1, N + 1] 里,最后 N + 1 这个元素我们不用找。因为在前面的 N 个元素都找不到的情况下,我们才返回 N + 1;
那么,我们可以采取这样的思路:就把 1 这个数放到下标为 0 的位置, 2这个数放到下标为 1 的位置,按照这种思路整理一遍数组。然后我们再遍历一次数组,第 1 个遇到的它的值不等于下标的那个数,就是我们要找的缺失的第一个正数。
这个思想就相当于我们自己编写哈希函数,这个哈希函数的规则特别简单,那就是数值为 i 的数映射到下标为 i - 1 的位置。
举个例子:
数组 [3, 4, -1, 1]
下标 0 1 2 3
1、nums[I] = 3,应该放到i-1 = 2的下标位置。也就是下标i与nums[I]-1的下标交换位置
[-1, 4, 3, 1]
0 1 2 3
2、nums[I] = -1,不符合要求,先不管了,进入下一个循环 nums[I] = 4 ,应该放到下标为3的位置,所以i和下标为nums[I]-1 = 3 的位置交换。
[-1, 1, 3, 4]
0 1 2 3
3、此时nums[i] = 1, 不符合等于 i +1 ,所以下标i要和nums[i]-1交换位置
[1, -1, 3, 4]
4、此时nums[I] = -1,不符合条件,进入下一个循环。nums[I] = 3符合条件、进入下一个循环,nums[I] = 4符合条件,循环结束。此时的数组为 [1, -1, 3, 4]。
5、此时我们再遍历该数组,将所有nums[I] != i+1的找出来即可。可以看到当i=1的时候,不符合,所以返回i+1,即该下标应该有的值。
func firstMissingPositive(nums []int) int {
len := len(nums)
for i:=0;i<len;i++{
for nums[i] > 0 && nums[i] <= len && nums[nums[i]-1] != nums[i] {
swap(nums, nums[i]-1, i)
}
}
for i:=0;i<len;i++{
if nums[i] != i + 1 {
return i + 1
}
}
return len + 1
}
func swap(nums []int, index1, index2 int ) {
nums[index1],nums[index2] = nums[index2],nums[index1]
}
所以:
根据41题的思路和解法,我觉得和这个很像。先给nums append两个0。
然后把上面的交换位置的代码复制过来。
然后再次进行遍历的时候,如果遇到不符合条件的,就把i+1存到res中,最终返回res。
func missingTwo(nums []int) []int {
nums = append(nums,0) //比41增加了这两行
nums = append(nums,0)
len := len(nums)
for i:=0;i<len;i++{
for nums[i] > 0 && nums[i] <= len && nums[nums[i]-1] != nums[i] {
swap(nums, nums[i]-1, i)
}
}
var res []int // 和41有区别的位置
for i:=0;i<len;i++{
if nums[i] != i + 1 {
res = append(res, i+1) // 和41有区别的位置
}
}
return res // 和41有区别的位置
}
func swap(nums []int, index1, index2 int ) {
nums[index1],nums[index2] = nums[index2],nums[index1]
}
复杂度分析:
内容参考:力扣 李weiwei的解法。