找到重复的数
给一个数组包含n+1个整数,每个整数都是在1到n之间(包括n),证明至少存在一个重复数字。假设只有一个重复的数字,找出这个数
- 不能修改这个数组,只能用一个常数的额外空间,运行时间复杂度少于n^2
- 只有一个重复的数,但是重复次数超过一次
思路一:
https://segmentfault.com/a/1190000003817671
- 采用二分搜索法,先选取n/2,按照抽屉原理,整个数组中如果小于等于n/2的数的数量大于n/2,说明1到n/2这个区间是肯定有重复数字的。
- 注意
我们比较的mid而不是nums[mid]
因为mid是下标,所以判断式应为cnt > mid,最后返回min
代码:
class Solution {
public:
int findDuplicate(vector<int>& nums) {
int min = 0, max = nums.size() - 1;
while(min <= max){
// 找到中间那个数
int mid = (max + min) / 2;
int cnt = 0;
// 计算总数组中有多少个数小于等于中间数
for(int i = 0; i < nums.size(); i++){
if(nums[i] <= mid){
cnt++;
}
}
// 如果小于等于中间数的数量大于中间数,说明前半部分必有重复
if(cnt > mid){
max = mid - 1;
// 否则后半部分必有重复
} else {
min = mid + 1;
}
}
return min;
}
};
思路二:
龟兔算法,时间复杂度为O(n)
http://blog.csdn.net/duxinyuhi/article/details/53379239
python代码参考:
http://bookshadow.com/weblog/2015/09/28/leetcode-find-duplicate-number/
详细原理参考:http://keithschwarz.com/interesting/code/?dir=find-duplicate
class Solution(object):
def findDuplicate(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
slow = 0;
fast = 0;
while True:
slow = nums[slow]
fast = nums[nums[fast]]
if slow == fast:
break
finder = 0;
while True:
slow = nums[slow]
finder = nums[finder]
if slow == finder:
return slow
C++代码
http://www.cnblogs.com/grandyang/p/4843654.html
class Solution {
public:
int findDuplicate(vector<int>& nums) {
int slow = 0, fast = 0, t = 0;
while (true) {
slow = nums[slow];
fast = nums[nums[fast]];
if (slow == fast) break;
}
while (true) {
slow = nums[slow];
t = nums[t];
if (slow == t) break;
}
return slow;
}
};