[LeetCode]287. Find the Duplicate Number

STL使用

Posted by JinFei on September 27, 2021

题目描述

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.

循环链表

  • 假如有数组 1,3,4,2,5
  • 那么对应下标 0,1,2,3,4
  • 从下标为 0 出发,根据f(n) 计算出一个值,以这个值为新的下标,再用这个函数计算,以此类推,直到下标超界。这样可以产生一个类似链表一样的序列。 建立数组到下标的映射 0 -> 1 -> 3 -> 2 -> 4 -> 5 -> nullptr
  • 如果有重复元素 ,那么此链表一定有环,并且重复元素即为环的入口,接下来就将转换成寻找链表环的入口的操作。
class Solution {
public:
    int findDuplicate(vector<int>& nums) {
        // vector<int> vec(nums);
        // for(int i = 0; i < vec.size(); i++){
        //     while(i != nums[i] - 1){
        //         if(nums[i] == nums[nums[i] - 1]){
        //             return nums[i];
        //         }
        //         else{
        //             swap(nums[i], nums[nums[i] - 1]);
        //         }
        //     }
        // }
        // return -1;
        int slow = 0;
        int fast = 0;
        slow = nums[slow];
        fast = nums[nums[fast]];
        while(slow != fast){
            slow = nums[slow];
            fast = nums[nums[fast]];
        }
        int pre = 0;
        while(pre != slow){
            pre = nums[pre];
            slow = nums[slow];
        }
        return pre;
    }
};

比较交换

  • 如果当前的数字不等于当前的位置,就把当前数字换到其对应的位置上去,然后依次类推,直到找到重复的元素为止。

    比较交换代码实现

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

STL解题思路

  • unordered_set使用
  • 如果能够在set集合里找到,则s.count(num)返回相应的个数
  • unordered_set containers do not allow for duplicate values, this means that the function actually returns 1 if an element with that value exists in the container, and zero otherwise.
  • unordered_set不允许有重复值,所以count实际返回值要么是1要么是0.
    • set基于红黑树实现,红黑树具有自动排序的功能,因此map内部所有的数据,在任何时候,都是有序的。
      unordered_set基于哈希表,数据插入和查找的时间复杂度很低,几乎是常数时间,而代价是消耗比较多的内存,无自动排序功能。底层实现上,使用一个下标范围比较大的数组来存储元素,形成很多的桶,利用hash函数对key进行映射到不同区域进行保存。

C++代码

class Solution {
public:
    int findDuplicate(vector<int>& nums) {
        unordered_set<int> s;
        for(auto num : nums){
            if(!s.count(num)){
                s.insert(num);
            }
            else{
                return num;
            }
        }
        return -1;
    }
};