【LeetCode】C++ :中等题 - 哈希表 287. 寻找重复数

287. 寻找重复数

难度中等1052

给定一个包含 n + 1 个整数的数组 nums ,其数字都在 1 到 n 之间(包括 1 和 n),可知至少存在一个重复的整数。

假设 nums 只有 一个重复的整数 ,找出 这个重复的数 。

 

示例 1:

输入:nums = [1,3,4,2,2]
输出:2

示例 2:

输入:nums = [3,1,3,4,2]
输出:3

示例 3:

输入:nums = [1,1]
输出:1

示例 4:

输入:nums = [1,1,2]
输出:1

 

提示:

  • 2 <= n <= 3 * 104
  • nums.length == n + 1
  • 1 <= nums[i] <= n
  • nums 中 只有一个整数 出现 两次或多次 ,其余整数均只出现 一次

 

进阶:

  • 如何证明 nums 中至少存在一个重复的数字?
  • 你可以在不修改数组 nums 的情况下解决这个问题吗?
  • 你可以只用常量级 O(1) 的额外空间解决这个问题吗?
  • 你可以设计一个时间复杂度小于 O(n2) 的解决方案吗?

这题我使用了哈希表,但是空间复杂度不满足题目要求,因此我看了看官方题解,收获了不少。

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

    }
};

 

1. 二分查找法

二分查找,用cnt[i]表示数组中小于等于i的个数

class Solution {
public:
    int findDuplicate(vector& nums) {
        int n = nums.size();
        int l = 1, r = n-1;
        int res = -1;

        while(l <= r){
            int mid = (l+r) >> 1;   //位运算右移一位;
            int cnt = 0;
            for(int i = 0; i < n; i++){
                cnt += (nums[i] <= mid);
            }
            if(cnt <= mid){
                l = mid + 1;
            }else{
                r = mid - 1;
                res = mid;
            }
        }
        return res;
    }
};

2. 快慢指针法 

快慢指针解法是能够明白的,官方说的是,这道题如果面试时想到是链表和环会有加分。看来难点就是不一样啊

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

 

你可能感兴趣的:(LeetCode,leetcode,算法,哈希表)