寻找重复数

题目描述:

给定一个包含 n + 1 个整数的数组 nums,其数字都在 1 到 n 之间(包括 1 和 n),可知至少存在一个重复的整数。假设只有一个重复的整数,找出这个重复的数。

示例:

输入: [1,3,4,2,2] 输出: 2

输入: [3,1,3,4,2] 输出: 3

解题思路:

按理这道题其实并不难,但是加了如下的条件就变态了

  1. 不能更改原数组(假设数组是只读的);
  2. 只能使用额外的 O(1) 的空间。

如果没有额外限制条件,我们很容易想到的方法有

  1. 使用哈希表判重,这违反了限制 2;
  2. 将原始数组排序,排序以后,重复的数相邻,即找到了重复数,这违反了限制 1;
方法:双重遍历判断
//go
func findDuplicate(nums []int) int {
    length := len(nums)
    for i := 0; i < length; i++ {
        for j := i+1; j < length; j++ {
            if nums[i] == nums[j] {
                return nums[i]
            }
        }
    }
    return 0
}
方法:二分查找

先猜一个数(取有效范围 [left, right] 的中位数 mid),然后统计原始数组中小于等于mid的个数cnt,如果cnt大于mid,则重复元素就在区间[left, mid]

//go
func findDuplicate(nums []int) int {
    length := len(nums)
    left, right := 1, length-1
    for left < right {
        mid := (left + right)>>1 //(left + right)/2 的位运算写法

        cnt := 0
        for _, num := range nums {
            if num <= mid {
                cnt++
            }
        }

        if cnt > mid {
            right = mid
        }else {
            left = mid+1
        }
    }
    return left
}
  • 时间复杂度:O(NlogN),二分法的时间复杂度为O(logN),在二分法的内部,执行了一次 for 循环,时间复杂度为O(N),故时间复杂度为O(NlogN)。
  • 空间复杂度:O(1),使用了一个 cnt 变量,因此空间复杂度为 O(1)。

地址:https://mp.weixin.qq.com/s/NY7ZGRJgKTwsF983vqhNow

 

posted @ 2020-09-14 09:44  small_lei_it  阅读(208)  评论(0编辑  收藏  举报