https://leetcode-cn.com/problems/find-the-duplicate-number/
这个题跟剑指Offer有一题寻找重复数差不多,但是这个题要求更高一点,要求不能修改原数组的元素,一开始的我要求都没看完就做了,我佛了。。。
public int findDuplicateFake(int[] nums) { for (int i = 0; i < nums.length; i++) { while ((i + 1) != nums[i]) { if (nums[nums[i] - 1] == nums[i]) { return nums[nums[i] - 1]; } int temp = nums[i]; nums[i] = nums[temp-1]; nums[temp-1] = temp; } } return 0; }
后来想了下,这个只有一个元素是重复出现的,那么其实可以把这个数组看成一条循环链表,LeetCode上有一题叫做寻找循环链表中的环的入口,这个题就有点类似了。
public int findDuplicate(int[] nums) {
int fast = 0, slow = 0;
while(true){
fast = nums[nums[fast]];
slow = nums[slow];
if(slow == fast){
fast = 0;
while (slow != fast){
fast = nums[fast];
slow = nums[slow];
}
return fast;
}
}
}
首先我们定义快慢两个指针,快指针一次走两步,慢指针一次走一步。
如果快慢指针指向的值相同,说明我们可能进入了环。那么我们假设我们所在的地方就是环的其中一个入口,我们让快指针重置,然后每个指针都走一步,直到它两相等即是入口。
这个证明好像是个数学问题,在链表题中有讲解。