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


    一.题目一

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

    例如:
      输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是重复的数字2或者3

    二.思路

    1. 运用哈希表不重复的特点,扫描数组,扫描得到的元素不在哈希表中,则把该元素放入哈希表,继续扫描;若扫描到的元素在哈希表中,则该元素为重复元素,返回该元素;
    2. 上述方法很简单,但是空间复杂度为O(n),考虑是不是能把空间复杂度降低一下?我们发现数组里面的所有数字都在0~n-1 的范围内,所以有如下想法:把数组重排的话,如果不重复,那么位置为i的元素大小应该也为i,如果有重复元素,位置为i的元素应该至少有两个元素,也就是出现了碰撞。因此我们决定重排数组,把元素放到对应的位置,一旦出现碰撞,则出现重复。

    三.代码

    方法一代码:

    //unordered_map
    bool duplicate(int numbers[], int length, int* duplication){
      
        unordered_map<int,int> umap;
    
        if(numbers == nullptr || length <= 0)
          return false;
    
        for(int i = 0;i < length;i++)
          if(numbers[i] < 0 || numbers[i] > length - 1)
            return false;
    
        for(int i = 0;i < length;i++){
          if(!umap.count(numbers[i])){
            *duplication = numbers[i];
            return true;
          }
            umap[numbers[i]] = i;
    
        }  
        return false;
    }

    方法二代码:

    //collision
    bool duplicate(int numbers[], int length, int* duplication){
        
        if(numbers == nullptr || length <= 0)
            return false;
    
        for(int i = 0;i < length;i++)
            if(numbers[i] < 0 || numbers[i] > length - 1)
                return false;
    
        for(int i = 0;i < length;i++){
    
            while(numbers[i] != i){
                if(numbers[i] == numbers[numbers[i]]){
                    *duplication = numbers[i];
                    return true;
                }
    
                int tmp = numbers[i];
                numbers[i] = numbers[tmp];
                numbers[tmp] = tmp;
    
            }
    
    
        }
        return false;
    
    }

    四.本题考点

    • 考查应聘者对一维数组的理解及编程能力。一维数组在内存中占据连续的空间,因此我们可以根据下标定位对应元素。
    • 考查应聘者分析问题的能力。当应聘者发现问题比较复杂时,能不能通过具体的例子找出其中的规律,是能否解决这个问题的关键所在。

    五.题目二

           在一个长度为 n+1 的数组里的所有数字都在 1~n 的范围内,所以数组中至少有一个数字是重复的。请找出数组中任意一个重复的数字,但不能修改输入的数组

    例如,

           如果输入长度为8的数组{2, 3, 5, 4, 3, 2, 6, 7},那么对应的输出是重复的数字2或者3。

    六.思路

    1. 考虑一个辅助数组,同样采用题目一的方法二,只不过这次是在辅助数组上做操作
    2. 上述方法空间复杂度为O(n),我们同样考虑如何降低空间复杂度。可以考虑二分查找的思路:我们把1~n的数字从中间的数字m分为两部分,前面一半为1~m,后面一半为m+1~n。如果前面1~m部分的数字的数目超过m,那么这一部分一定包含重复的数字;否则,另一半m+1~n的部分必定包含重复数字。我们可以把包含重复数字的部分继续一分为二,直到找到一个重复的数字。在这个过程中,我们要加一个子函数,计算某一部分里数字的部分。

    七.代码

    方法一代码

    int getDuplication(const int* numbsers,int length){
      
      if(numbers == nullptr || length <= 0)
        return false;
    
      int tmp[length];
    
      for(int i = 0;i < length; i++){
        if(numbers[i] < 1 || numbers[i] > length)
          return 0;
    
        if(tmp[i])
          return 1;
    
        tmp[i] = numbers[i];
      }
    
      return 0;
    
    }

    方法二代码

    int getDuplication(const int* numbers,int length){
        if(numbers == nullptr || length < 0)
            return 0;
    
        int start = 0;
        int end = length - 1;
    
        while(start <= length){
            int mid = start + ((end - start) >> 1);
    
            int count = countRange(numbers,length,start,mid);
            if(start == end){
                if(count > 1)
                    return start;
                else
                    return -1;
            }
    
            if(count > (mid - start + 1))
                end = mid - 1;
    
            else
                start = mid + 1;
    
        }
    
        return -1;
    
    }
    
    int countRange(int* numbers,int length,int start,int end){
        
        if(numbers == nullptr)
            return 0;
    
        int count = 0;
        for(int i = start;i < end;i++){
            if(numbers[i] >= start && numbers[i] <= end)
                ++count;
        }
    
        return count;
    }

    八.本题考点

    • 考查应聘者对一维数组的理解及编程能力。一维数组在内存中占据连续的空间,因此我们可以根据下标定位对应的元素。
    • 考查应聘者对二分查找算法的理解,并能快速、正确的实现二分查找算法的代码
    • 考查应聘者的沟通能力。应聘者只有具备良好的沟通能力,才能充分了解面试官的需求,从而有针对性的选择算法解决问题。
  • 相关阅读:
    Codeforces 1149 B
    Tenka1 Programmer Contest 2019 D
    BZOJ 1001 [BeiJing2006]狼抓兔子
    Codeforces 741 D
    HDU 5306 Gorgeous Sequence
    HDU 6521 Party
    Codeforces 912A/B
    Educational Codeforces Round 35 B/C/D
    Codeforces 902D/901B
    Codeforces 902B
  • 原文地址:https://www.cnblogs.com/ovs98/p/9852939.html
Copyright © 2020-2023  润新知