题目
快慢指针法
由于存在重复的数字,因此将数组看作链表索引后,必然存在环,那么环的入口数字即为重复数字。
首先假设环长度为 L ,从起始位置到环的入口长度为 a ,环入口位置到快慢指针相遇位置的长度为 b ,从快慢指针相遇位置到下一次进入环(环入口)的长度为 c ,那么环的长度为: L = b + c L = b + c L=b+c 。
假设快慢指针相遇时各自走了 s l o w = a + b slow=a+b slow=a+b , f a s t = 2 ( a + b ) = a + b + k L fast=2(a+b)=a+b+kL fast=2(a+b)=a+b+kL ,因此可以解得:
a = ( k − 1 ) L + c a=(k-1)L+c a=(k−1)L+c
根据快慢指针的性质,可以发现当两指针相遇时,快指针若再走 L + c L+c L+c 的距离即可到达环的入口,也就是说此时慢指针走 a 的距离,刚好可以凑出快指针所需的距离并且同时到达环的入口,从而得到重复数字:
class Solution {
public:
int findDuplicate(vector<int>& nums) {
int slow = 0, fast = 0;
while(1) {
slow = nums[slow];
fast = nums[nums[fast]];
if(slow == fast) {
slow = 0;
break;
}
}
while(1) {
slow = nums[slow];
fast = nums[fast];
if(slow == fast)
return slow;
}
return 0;
}
};