287. 寻找重复数
思路
快慢指针
一个图,快指针跑两步,满指针跑一步,如果遇到相同的节点肯定有环。
有环如何找到起点?把慢指针放到开头,快指针也降速,一步一步跑,再次遇到相同的就是答案。
证明如下
x 是环的起点
y 是相遇点
L是环长度
c是环长度减去y
得到
2
(
x
+
y
)
=
x
+
y
+
k
L
2(x+y)=x+y+kL
2(x+y)=x+y+kL
x
=
(
k
−
1
)
L
+
(
L
−
y
)
=
(
k
−
1
)
L
+
c
x=(k-1)L + (L-y)=(k-1)L+c
x=(k−1)L+(L−y)=(k−1)L+c
所以我们把slow放到开头再走x位置,最后fast走了(k-1)L+c也回到x
class Solution {
public:
int findDuplicate(vector<int>& nums) {
int slow = 0, fast = 0;
do{
slow = nums[slow];
fast = nums[nums[fast]];
}while(nums[slow] != nums[fast]);
slow = 0;
while(slow != fast){
slow = nums[slow];
fast = nums[fast];
}
return slow;
}
};