每日一题|22-9-26|面试题 17.19. 消失的两个数字| golang

面试题 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的解法。

        

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值