287. Find the Duplicate Number (快慢指针)

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.

Example 1:

Input: [1,3,4,2,2]
Output: 2

Example 2:

Input: [3,1,3,4,2]
Output: 3

Note:

  1. You must not modify the array (assume the array is read only).
  2. You must use only constant, O(1) extra space.
  3. Your runtime complexity should be less than O(n2).
  4. There is only one duplicate number in the array, but it could be repeated more than once.

题目设定的问题是N+1个元素都在[1,n]这个范围内。这样我们可以用那个类似于 ‘缺失的第一个正数’ 这种解法来做,但是题意限制了我们不能修改原数组,我们只能另寻他法。也就是本编题解讲的方法,将这个题目给的特殊的数组当作一个链表来看,数组的下标就是指向元素的指针,把数组的元素也看作指针。如0是指针,指向nums[0],而nums[0]也是指针,指向nums[nums[0]].
这样我们就可以有这样的操作

int point = 0;
while(true){
point = nums[point]; // 等同于 next = next->next; 
}


链表中的环
假设有这样一个样例:[1,2,3,4,5,6,7,8,9,5]。如果我们按照上面的循环下去就会得到这样一个路径: 1 2 3 4 5 [6 7 8 9] [6 7 8 9] [6 7 8 9] . . .这样就有了一个环,也就是6 7 8 9。point会一直在环中循环的前进。
这时我们设置两个一快(fast)一慢(slow)两个指针,一个每次走两步,一个每次走一步,这样让他们一直走下去,直到他们在重复的序列中相遇,

 1 class Solution {
 2 public:
 3     int findDuplicate(vector<int>& a) {
 4         int slow = 0;
 5         int fast = 0;
 6         while(true) {
 7             fast = a[a[fast]];
 8             //fast = fast->next->next;
 9             slow = a[slow];
10             if(fast==slow) break;
11         }
12         fast = 0;
13         while(true) {
14             fast = a[fast];
15             slow = a[slow];
16             if(fast==slow) return fast;
17         }
18         return -1;
19     }
20 };

55链表中环的入口结点

原文地址:https://www.cnblogs.com/zle1992/p/12584905.html