面试题51. 数组中重复的数字

本文介绍了三种在数组中查找重复数字的有效算法:Set法、减最大值法和交换法。每种方法都详细解释了其工作原理,并提供了Java代码实现。通过这些算法,可以高效地解决数字重复的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

思路1:Set法
使用Set,空间复杂度为O(n),时间复杂度为O(n)
从头遍历数组,如果不在Set中,则存入Set;如果在Set中,说明是重复的数字。

Java 代码如下:

public boolean duplicate(int numbers[],int length,int [] duplication) {
    Set set = new HashSet();
    for(int i=0; i<length; i++) {
        if(!set.contains(numbers[i])) {
         set.add(numbers[i]);
     }else {
         duplication[0] = numbers[i];
         return true;
     }
    }
    return false;
}

思路2:减最大值法
假设现在遍历到数组的第i个元素,做如下计算:
numbers[numbers[i]] -= numbers.length

这里写图片描述

如果检测到numbers[numbers[i]]的值小于0,则说明重复。比如当遍历到第二个2时,发现numbers[2] == -6 (由1 - 7计算得来),则2重复了。
这种方法不使用额外的空间复杂度,同时,时间复杂度也为O(n)

看代码容易加深理解,Java代码如下:

 public boolean duplicate(int numbers[],int length,int [] duplication) {

      //不使用Set辅助
      for(int i = 0; i < length; i++) {
        int index = numbers[i];
          if(index < 0) {
              index += length;
          }

        if(numbers[index] < 0) {
              if(index < 0) {
                  index += length;
              }
            duplication[0] = index;
            return true;
        }
        numbers[index] -= length;
    }
    return false;
  }

思路3:交换法
假设当前遍历第i个元素,则交换numbers[i]和numbers[numbers[i]],直到满足numbers[i] = i

这里写图片描述

代码如下:

 public boolean duplicate(int numbers[],int length,int [] duplication) {

      // 方法三 交换法
      for(int i = 0; i < length; i++) {
          while(numbers[i] != i) {
              if(numbers[i] == numbers[numbers[i]]) {
                  duplication[0] = numbers[i];
                  return true;
              }
              int t = numbers[numbers[i]];
              numbers[numbers[i]] = numbers[i];
              numbers[i] = t;
          }
      }
    return false;
  }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值