剑指Offer:数组中重复的数字

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

      首先想到的方法是将数组进行排序,我们遍历一遍数组就可以找出重复的数字了。排序一个数组的时间复杂度为O(nlogn)。

      我们还可以使用哈希表来解决这一问题。我们从头到尾遍历数组,如果哈希表中不存在当前遍历的数字,那么就在哈希表中存放这个数字;如果当前遍历的数字存在哈希表中了说明这个数字就是重复的。这个方法的时间复杂度为O(n),但是空间复杂度为O(n)。我们思考有没有空间复杂度为O(1)的方法。

      根据题目我们知道数组大小为n,所有数字的范围为0至n-1,显然,如果不存在重复的数字当数组排序后下标i对应的数字就是i;如果存在重复的数字有些位置存在多个数字,而有的位置没有数字。

算法思路如下:
      从头遍历数组中的每个数字,每次扫描到的数字记为m。当扫描到下标为i的数字是,首先比较m是否等于i:

  • 如果相等,直接扫描下一个数字;
  • 如果不相等,再拿m和第m个数字相比较:
    • 如果它和第m个数字相等那么我们就找到了一个重复数字。
    • 如果它和第m个数字不相等,就把第i个数字和第m个数字交换,把m放到属于它的位置上。再重复这个比较、交换过程,直至找到重复的数字。

实现代码:

public static boolean DuplicatedNum(int numbers[],int length,int[] duplication) {
       if(numbers==null||length==0||duplication==null){
        return false;
    }
       for(int i=0;i<length;i++){
           if(numbers[i]<0||numbers[i]>length-1){
               return false;
           }
       }
    for(int i=0;i<numbers.length;i++){
        int m=numbers[i];
        if(i==m){
            continue;
        }else{
            if(m==numbers[m]){
                   duplication[0]=m;
                return true;
            }else{
                int temp = numbers[i];
                   numbers[i] = numbers[m];
                   numbers[m] = temp;
            }
        }
    }
    return false;
   }

猜你喜欢

转载自blog.csdn.net/qq_25343557/article/details/79660451