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

来源:互联网 发布:西门子工业组态软件 编辑:程序博客网 时间:2024/06/01 19:37

题目描述
在一个长度为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;  }
原创粉丝点击