leetcode【287】【tag Array Two pointers】Find the Duplicate Number【c++版本,時間89%,兩種解法】

問題描述:

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.

源碼:

首先最直觀的做法就是排序,時間O(n*logn),空間O(1)。

class Solution {
public:
    int findDuplicate(vector<int>& nums) {
        int n = nums.size();
        sort(nums.begin(), nums.end());
        for (int i=0; i<n-1; i++){
            if(nums[i] == nums[i+1])    return nums[i];
        }
        return 0;
    }
};

顯然不能滿足要求,肯定有O(n)的做法,但是它這個重複元素不止出現了一次,想了半天也沒想出來了,翻了一下solution,也看了一下人家博客纔看懂。

根據題目,包含 n + 1 個整數的數組 nums,其數字都在 1 到 n 之間(包括 1 和 n),可知至少存在一個重複的整數。
對應地,如果設計一個指針 i,每次移動到 nums[i],由於存在重複整數,一定存在節點入度大於 1,即該指針的遍歷軌跡中存在環,且重複整數爲環的入口。
因此可以設計兩個運動速度不同的快慢指針,經過一段時間後它們會在環中相遇。
之後尋找環入口的思路與 leetcode【141、142】Linked List Cycle、Linked List Cycle II【c++,雙指針法,技巧,時間94%,空間100%】相同,將其中一個指針退回到數組起點,與另一相遇處的指針以相同速度向前遍歷,相遇處即爲重複整數。

時間89.4%

class Solution {
public:
    int findDuplicate(vector<int>& nums) {
        int fast = nums[0], slow = nums[0];
        do {
            slow = nums[slow];
            fast = nums[nums[fast]];
        } while(fast != slow);
        // cout<< fast <<endl;
        slow = nums[0];
        while (fast != slow){
            slow = nums[slow];
            fast = nums[fast];
        }
        return fast;
    }
};

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章