给定一个包含 n + 1 个整数的数组 nums,其数字都在 1 到 n 之间(包括 1 和 n),可知至少存在一个重复的整数。假设只有一个重复的整数,找出这个重复的数。
示例 1:
输入: [1,3,4,2,2]
输出: 2
示例 2:
输入: [3,1,3,4,2]
输出: 3
说明:
不能更改原数组(假设数组是只读的)。
只能使用额外的 O(1) 的空间。
时间复杂度小于 O(n2) 。
数组中只有一个重复的数字,但它可能不止重复出现一次。
思路:这道题很经典,我面试的时候被问过,有好多种不同的做法,但是被限制了好多条件之后,这些做法就不能用了。
我们先从最笨的方法开始,枚举1 - n,看一看它在数组中出现了几次,如果出现的次数超过1次,说明它是重复的数字,这样直接暴力的话复杂度就是O(n^2)。
我们可以进行优化一下,两层循环,里面那一层计数是优化不了,我们可以考虑优化一下外层的循环。如果数字x出现的次数大于1,说明x重复了,同样如果数字x到y之间出现的次数大于(y-x+1)次,那么说明重复的数字必然出现在x到y之间。
由此我们可以很容易地想到二分法,计数1到n/2,如果出现的次数大于n/2,说明重复的数字在区间1-(n/2)之间,否则重复的数字出现在右边。
参考代码:
class Solution {
public int findDuplicate(int[] nums)
{
int l = 1, r = nums.length - 1;
while(l < r)
{
int mid = (l + r) / 2;
int cnt = 0;
for(int i = 0;i < nums.length;i++)
if(nums[i] <= mid && nums[i] >= l)
cnt++;
if(cnt > (mid - l + 1))
r = mid;
else
l = mid + 1;
}
return l;
}
}