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

剑指offer

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

题目描述:

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

  1. 数组排序

    把输入数组作排序处理,在重头扫描。采用排序,时间复杂度O(nlogn)。

  2. 哈希表

    利用Hashset,表中不能存相同数据的特征。表中如果没有就添加进去,有的话即发现重复的数字。

     private static int duplicate(int[] numbers) {
            for ( int i= 0 ; i<numbers.length; i++) {
    
                int index = numbers[i];
    
                if (index >= numbers.length) {
                    index -= numbers.length;
                }
                if (numbers[index] >= numbers.length) {
                    return index;
                }
                numbers[index] = numbers[index] + numbers.length;
    
            }
    
            return - 1 ;
        }
    

    还有一种也类似哈希表的处理方式。

    private static int duplicate(int[] numbers) {  
     if (numbers == null || numbers.length <= 0){  
             return -1;  
      }  
         boolean[] k = new boolean[numbers.length];  
         for (int i : numbers) {  
             if (i < 0 || i > numbers.length - 1){  
                 return -1;  
             }  
             //如果为true说明已经赋值过,即发现重复数字  
             if (k[i] == true){  
                 return i;  
             }  
             k[i] = true;  
         }  
         return -1;  
     }  
    
  3. 空间复杂度为O(1)的算法

    从头到尾依次扫描这个数组中的每个数字。当扫描到下标为i的数字,首先比较这个数字(用m来表示)是不是等于i。如果是,则接着扫描下一个数字;如果不是,则再拿它和第m个数字进行比较。

    如果它和第m个数字相等,就找到了重复的数字;如果不相等,就把第i个数字和第m个数字交换。接着重复这个比较,交换的过程。

    在这里插入图片描述

    private static int duplicate(int[] numbers) {  
     if (numbers == null || numbers.length <= 0){  
          return -1;  
      }  
      for (int i : numbers) {  
          if (i < 0 || i > numbers.length - 1){  
              return -1;  
          }  
      }  
      //从0开始依次比较  
      for (int i = 0; i < numbers.length; i++) {  
          //当数组当前值不等于数组的下标时  
          while (numbers[i] != i){  
              //如果数组值 等于 数组值对应下标的数组值(有点绕),则找到重复值  
              if (numbers[i] == numbers[numbers[i]]){  
                  return numbers[i];  
              }  
              //相当于交换swap(array[i],array[array[i]]),  
              {  
                  int t = numbers[i];  
                  numbers[i] = numbers[t];  
               numbers[t] = t;  
              }  
          }  
      }  
      return -1;  
    }  
    } 
    
  4. 牛客网的一种很牛逼的算法

    结合代码看,如果一个数被访问了,设置对应数作为下标即给numbers[index]赋值为numbers[index]+length,当下一次遇到相同数时,numbers[index]会大于length。注意,当访问已经赋值过的数时,即index >= length,要进行 index -= length。非常机智!!!

    private static int duplicate(int[] numbers) {   
    for ( int i= 0 ; i<numbers.length; i++) {  
    
    int index = numbers[i];  
    
    if (index >= numbers.length) {  
       index -= numbers.length;  
    	}     
    if (numbers[index] >= numbers.length) {  
       return index;  
    	}
     numbers[index] = numbers[index] + numbers.length;  
    }
    	return -1;   
    } 
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值