###### tags: `Leetcode` `medium` `pointer` `python` `c++` `Top 100 Liked Questions` # 287. Find the Duplicate Number ## [題目連結:]https://leetcode.com/problems/find-the-duplicate-number/ ## 題目: Given an array of integers ```nums``` containing ```n + 1``` integers where each integer is in the range ```[1, n]``` inclusive. There is only **one repeated number** in ```nums```, return this repeated number. You must solve the problem **without** modifying the array ```nums``` and uses only constant extra space. **Follow up:** * How can we prove that at least one duplicate number must exist in nums? * Can you solve the problem in linear runtime complexity? **Example 1:** ``` Input: nums = [1,3,4,2,2] Output: 2 ``` **Example 2:** ``` Input: nums = [3,1,3,4,2] Output: 3 ``` ## 解題想法: * 給一數組,共有n+1個數字,由1~n組成, * 只有一數出現兩次,找出該數 * time: O(n) * space: O(1) * **技巧** * 將位置與數字關係結合: ``` python= pos= 0 1 2 3 4 nums= [1,3,4,2,2] 抽象想!! pos->nums->pos->nums...... 為0->1 1->3 2->4 3->2 4->2 * 即nums[i]存的是下個要指的位置 * 所以可化為: 0->1->3->2->4->2->4.......loop ``` * 使用pointer: * **可想成找環的問題** => **重複值=環的入口** * 證明: * 設 **環的長度為(B+C)** 進入環之前的路為**A** ``` python= (A) (重複點) (B) (x) ---------->----------> | | ----------- C ``` * 設slow與fast相遇點為x * 則slow共走了A+B * fast走了A+2B+C * 因為fast=2 * slow * 所以A+2B+C=2A+2B * 所以**A=C** * 可以得證: * 對於原點而言,走A的距離,相當於**同時從相遇點x走A的距離** 彼此相交的位置,即為重複值 ## Python: ``` python= class Solution(object): def findDuplicate(self, nums): """ :type nums: List[int] :rtype: int """ slow=nums[0] fast=nums[nums[0]] while fast!=slow: slow=nums[slow] fast=nums[nums[fast]] start=0 #起始 while start!=fast: #此處fast已經為fast slow相交處 #各自一步步移動 start=nums[start] fast=nums[fast] return start result=Solution() ans = result.findDuplicate(nums = [1,3,4,2,2]) print(ans) ``` ## C++: ``` cpp= class Solution { public: int findDuplicate(vector<int>& nums) { int slow=nums[0],fast=nums[nums[0]]; while (slow!=fast){ slow=nums[slow]; fast=nums[nums[fast]]; } int start=0; while (start!=fast){ start=nums[start]; fast=nums[fast]; } return start; } }; ```