zoukankan      html  css  js  c++  java
  • 【剑指Offer-数组】面试题3:数组中的重复数字

    题目描述

    在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中任意一个重复的数字。 例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是第一个重复的数字2。

    思路1

    先排序,然后遍历数组,如果 nums[i]==nums[i+1],则说明 nums[i] 重复,返回 nums[i] 即可。代码如下:

    class Solution {
    public:
        int findRepeatNumber(vector<int>& nums) {
            sort(nums.begin(), nums.end());
    
            for(int i=0; i<nums.size()-1; i++){
                if(nums[i]==nums[i+1]) return nums[i];
            }
            return 0;
        }
    };
    
    • 时间复杂度:O(nlogn)
    • 空间复杂度:O(1)

    思路2

    使用哈希表。从头到尾扫描数组,每扫描到一个数字时,就用O(1)的时间来判断哈希表中是否包含了该数字。如果包含,就找到了一个重复数字;如果没有包含,就把该数字加入到哈希表中。

    class Solution {
    public:
        int findRepeatNumber(vector<int>& nums) {
            vector<bool> hash(nums.size(), false);
    
            for(int i=0; i<nums.size(); i++){
                if(hash[nums[i]]==true) return nums[i];
                else hash[nums[i]] = true;
            }
            return 0;
        }
    };
    
    • 时间复杂度:O(n)
    • 空间复杂度:O(n)

    思路3

    使用和缺失的第一个正数类似的方法。遍历 nums,并将 nums[nums[i]] 设为 -nums[nums[i]],这样,在遍历的过程中,如果我们先 nums[nums[i]] 为负数,则说明 nums[i] 是重复的。

    这个方法还有一个问题要解决,就是 0 的问题。我们设置一个标志 findZero 表示是否找到了 0,如果第一次找到 0,则将 findZero 设为 true,如果我们在找到 0,则将 0 的下标返回即可。代码如下:

    class Solution {
    public:
        int findRepeatNumber(vector<int>& nums) {
            bool findZero = false;
            for(int i=0; i<nums.size(); i++){
                int idx = abs(nums[i]);
                if(nums[idx]==0){
                    if(findZero==true) return idx;
                    else findZero = true;
                }else if(nums[idx]<0){
                    return idx;
                }else{
                    nums[idx] = -nums[idx];
                }
            }
            return 0;
        }
    };
    
    • 时间复杂度:O(n)
    • 空间复杂度:O(1)

    思路4

    遍历数组,如果 nums[i]==i,说明 i 没有缺失,判断下一个元素。如果 nums[i]!=i,则交换 nums[i] 和 nums[nums[i]],如果在交换的过程中发现 nums[i]==nums[nums[i]],则返回 nums[i]。代码如下:

    class Solution {
    public:
        int findRepeatNumber(vector<int>& nums) {
            for(int i=0; i<nums.size(); i++){
                if(nums[i]!=i){
                    while(nums[i]!=i){
                        if(nums[i]==nums[nums[i]]) return nums[i];
                        else swap(nums[i], nums[nums[i]]);
                    }
                }
            }
            return 0;
        }
    };
    
    • 时间复杂度:O(n)
    • 空间复杂度:O(1)
  • 相关阅读:
    呼叫中心获取sip数据报文
    【代码总结】GD库中简单的验证码
    【代码学习】PHP中GD库的使用
    【漏洞详解】文件包含漏洞
    讲两道常考的阶乘算法题
    如何高效解决接雨水问题
    如何判定括号合法性
    二分查找高效判定子序列
    一道数组去重的算法题把东哥整不会了
    如何高效寻找素数
  • 原文地址:https://www.cnblogs.com/flix/p/12122036.html
Copyright © 2011-2022 走看看