面试题三:寻找数组中重复的数字

在长度n的数组中,值的范围是0~n-1,数组中必定重复了,不知道哪个数字重复了,请找出任意对应数字
方法1:先排序,后遍历 O(nlogn+n)
方法2:不创建新空间,利用值与与下标替换的方法 两个循环,但第二个循环最多两次,所以时间O(n)
如 {2,3,1,0,2,5,3} 下标0的值是2,那么1和2调换位置,
{1,3,2,0,2,5,3} 继续下标0的值是1,那么1和3调换位置,
{3,1,2,0,2,5,3} 继续下标0的值是3,那么0和3调换位置,
{0,1,2,3,2,5,3} 下标与值相同,进入新下标,下标4
{0,1,2,3,2,5,3} 下标4的值是2,准备调换时发现下标2,已经有对应了,则找到重复了

  int duplicate( int array[]){
          if(array==null||array.length==0)
              return -1;
          for(int i=0;i<array.length;i++){
              if(array[i]<0||array[i]>array.length-1)
                  return -1;
          }
          for(int i=0;i<array.length;i++){
              while(array[i]!=i){
                  if(array[i]==array[array[i]])
                      return array[i];
                  
                  int temp=array[i];
                  array[i]=array[temp];
                  array[temp]=temp;
              }
          }
          return -1;
      }  

 

方法3:使用哈希表,如果表中没有则创建,有了就找到了 哈希表O(n) 时间O(n)
如果不修改原数组
方法4:创建新数组空间,进行类似计数排序的方法进行 O(n+n),空间O(n)

 int duplicate( int array[]){
          if(array==null||array.length==0)
              return -1;
          for(int i=0;i<array.length;i++){
              if(array[i]<0||array[i]>array.length-1)
                  return -1;
          }
          int B[]=new int [array.length];
          for(int i=0;i<array.length;i++){
              if(B[array[i]]!=0)
                  return B[array[i]];
              B[array[i]]++;
          }
          return -1;
      }

方法5:按照二分查找的思路,以值的范围为中心进行分割 时间O(nlogn)(不改变原数组)
如{2,3,1,0,2,5,3} n=7,值的范围为0~6,
1.寻找中间数字 (6+0)/2
2.按中间数字左右分割 0~2, 3~6
3.计数,统计左区间这几个数字在数组中出现的次数
如果次数大于左区间数字的个数,则重复的值在左区间,否则在右区间 3个数出现4次,左区间
4.假如找到的区间个数为1,则找到了;否则对找到的区间再次分区
5。重复步骤1
注意:该方法不能找出所有重复的数
注意事项:数组为空。

posted @ 2020-03-29 14:13  浪波激泥  阅读(439)  评论(0编辑  收藏  举报