题目描述:
给定一个包含 n + 1 个整数的数组 nums,其数字都在 1 到 n 之间(包括 1 和 n),可知至少存在一个重复的整数。假设只有一个重复的整数,找出这个重复的数。
示例:
输入: [1,3,4,2,2] 输出: 2
输入: [3,1,3,4,2] 输出: 3
解题思路:
按理这道题其实并不难,但是加了如下的条件就变态了
- 不能更改原数组(假设数组是只读的);
- 只能使用额外的
O(1)
的空间。
如果没有额外限制条件,我们很容易想到的方法有
- 使用哈希表判重,这违反了限制 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