Given an array nums containing n + 1 integers where each integer is between 1 and n (inclusive), prove that at least one duplicate number must exist. Assume that there is only one duplicate number, find the duplicate one.
Note:
- You must not modify the array (assume the array is read only).
- You must use only constant, O(1) extra space.
- Your runtime complexity should be less than
O(n2)
. - There is only one duplicate number in the array, but it could be repeated more than once
非常好的题目,开始是用二分做的,比如取数组为{1,2,3,3,4,5},mid应该是(5+1)/2 = 3,那么,如果小于等于mid的数的个数如果超过了3,那么重复的数字一定出现在[l,mid]之间,否则出现在[mid + 1,r]之间。以该数组为例,中位数为3,小于等于3的数一共有4个,大于3的数有两个,所以重复的数字在[1,3]之间。
发现效率挺感人的,看了一下discuss,恍然大悟,这题和142本质是一样的!
http://blog.csdn.net/accepthjp/article/details/53213998
这里说一下怎么转化成链表找环,把数组中的每一个下标和对应的数看成有向图中一个点到另一个点的边。
如果有一个数重复出现,那么一定有多个点指向它,因为它自己又必须指向一个数,那么这里面一定存在一个以他为起点的环,接下来只要找到这个换就行了。
一旦转化成142,后面应该就知道怎么做了,详细推导见上面的142题链接。
class Solution {
public:
int findDuplicate(vector<int>& nums) {
if (nums.size() > 1)
{
int slow = nums[0];
int fast = nums[nums[0]];
while (slow != fast)
{
slow = nums[slow];
fast = nums[nums[fast]];
}
fast = 0;
while (fast != slow)
{
fast = nums[fast];
slow = nums[slow];
}
return slow;
}
return -1;
}
};