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;
    }
};

 

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