LeetCode题解287- Find the Duplicate Number(C++)

题目:

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.


思路:思路完全同 Leetcode题解142- Linked List Cycle II(C++),不过问的问题不一样罢了。在142题中问的是在链表中寻找环的入口点,本题中问的是寻找重复的某个数。将本题的题目抽象,可以完全等同与142题。

Intuition

If we interpret nums such that for each pair of index ii and value v_ivi, the "next" value v_jvj is at index v_ivi, we can reduce this problem to cycle detection. See the solution to Linked List Cycle II for more details.

Algorithm

First off, we can easily show that the constraints of the problem imply that a cycle must exist. Because each number in nums is between 11 and nn, it will necessarily point to an index that exists. Therefore, the list can be traversed infinitely, which implies that there is a cycle. Additionally, because 00 cannot appear as a value in numsnums[0] cannot be part of the cycle. Therefore, traversing the array in this manner from nums[0] is equivalent to traversing a cyclic linked list. Given this, the problem can be solved just like Linked List Cycle II.

To see the algorithm in action, check out the animation below:

  • Time complexity : O(n)O(n)

  • Space complexity : O(1)O(1)


代码:

class Solution {
public:
    //287. Find the Duplicate Number
    int findDuplicate(vector<int>& nums) {
        if(nums.size() < 2) return -1;
        int fast = nums[0], slow = nums[0];  //快慢双指针
        do{
            fast = nums[nums[fast]];
            slow = nums[slow];
        }while(fast != slow);         //在环中某个点必定相遇
        int ptr1 = nums[0];  //ptr1从头触发
        int ptr2 = slow;    
        while(ptr1 != ptr2){     //在环的入口处,ptr1和ptr2相遇。而出口处的值就是我们要求的重复值。
            ptr1 = nums[ptr1];
            ptr2 = nums[ptr2];
        }
        return ptr2;
    }
};

猜你喜欢

转载自blog.csdn.net/u014694994/article/details/80576382