面试题3:数组中重复的数字

找出数组中重复的数字。

在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。

方法1:哈希表

class Solution {
public:
    int findRepeatNumber(vector<int>& nums) {
        vector<int> hashNum(nums.size(), 0); //哈希表存储数字出现的次数;
        for(auto x : nums){
            if(hashNum[x]) //出现了就返回;
                return x;
            hashNum[x]++; //没出现就添加进去;
        }
        return -1;
    }
};

时间复杂度:$ O(n) $ ,空间复杂度:$ O(n)$

方法2:原地交换

将每一个数字放回到自己的位置,当扫描到下标为 \(i\) 的数字 \(num[i]\) 时,如果 $num[i]==i $,说明该数字放在了正确的位置上,否则的话看一下它本来应该在的位置 \(num[i]\) ,即 \(num[num[i]]\) 上的数字为多少,二者相等的话说明出现了重复,不相等的话就交换一下。

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

时间复杂度:$ O(n) $ ,空间复杂度:$ O(1)$

拓展题:不修改数组找出重复的数字

在一个长度为n+1的数组 nums 里的所有数字都在 1~n 的范围内。所以数组中至少有一个数字是重复的。请找出数组中任意一个重复的数字。

不修改数组,不新增数组,使用二分法。该方法不保证找到所有的重复数字,比如:{2,3,5,4,3,2,6,7}。

class Solution {
public:
    int findRepeatNumber(vector<int>& nums) {
        int left = 1, right = nums.size() - 1;
        while(left <= right){
            int middle = ((right - left) >> 1) + left;
            int count = conutNums(nums, left, middle);

            if(left == right){
                if(count > 1)
                    return left;
                else
                    break;
            }

            if(count > (middle - left + 1))
                right = middle;
            else    
                left = middle + 1;
        }
        return -1;
    }

    int conutNums(vector<int>& nums, int left, int right){
        int count = 0;
        for(auto n : nums){
            if(n >= left && n <= right)
                count++;
        }
        return count;
    }
};
posted @ 2021-11-13 10:55  三年终  阅读(59)  评论(0)    收藏  举报