您的位置:首页 > 职场人生

剑指offer:面试题3—数组中重复的数字

2019-05-31 17:08 459 查看

题目描述

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

解决(代码在牛客网上通过):

1.将数组排序,从头至尾扫描排序后的数组,即可。

[code]import java.util.Arrays;
public boolean duplicate(int numbers[],int length,int [] duplication) {
boolean result=false;
if(numbers==null) return false;
Arrays.sort(numbers);
for(int i=0;i<numbers.length-1;i++){
if(numbers[i]==numbers[i+1]){
duplication[0]=numbers[i];
result=true;
break;
}
}
return result;
}

排序所需时间复杂度为O(nlogn)

2.使用大小为n的哈希表来解决

[code] public boolean duplicate(int numbers[],int length,int [] duplication) {
int[] a=new int[length];
boolean result=false;
for(int i=0;i<length;i++){
if(a[numbers[i]]==0){
a[numbers[i]]++;
}else if(a[numbers[i]]==1){
duplication[0]=numbers[i];
result=true;
break;
}
}
return result;
}

时间复杂度O(n),空间复杂度O(n)

3.空间复杂度O(1)的方法

从头至尾扫描数组中的每个数字,当扫描到下标为i的数字m时,首先比较这个数字m是不是等于i,如果是,则继续扫描;如果不是,则与下标为m的数字比较,如果相等则找到重复数字;如果不等,则交换位置。

[code]public boolean duplicate(int numbers[],int length,int [] duplication) {
boolean result=false;
if(numbers==null) return false;
for(int i=0;i<length;i++){
if(numbers[i]!=i){
int flag=numbers[numbers[i]];
if(flag==numbers[i]){
result=true;
duplication[0]=flag;
break;
}
numbers[numbers[i]]=numbers[i];
numbers[i]=flag;
}
}
return result;
}

时间复杂度为O(n),空间复杂度O(1)

4.不修改数组找出重复的数字

题目:长度为n+1的数组里的所有数字都在1~n范围内,所以至少有一个数字是重复的,请找出任意一个重复的数字,但不能修改输入的数组。

1)创建一个新的数组,一次复制到对应下标位,即可判断重复。

空间复杂度O(n)

2)666方法

举例:数组{2,3,5,4,3,2,6,7},1~7,8个数字,
 中间数字4将1~7分成两段,1~4,5~7;1~4出现了5次,5~7出现了3次;则重复数字出现在1~4;
 1~4一分为二,1~2出现了两次,3~4出现了三次,则重复数字出现在3~4;

[code]public static boolean duplicate(int numbers[],int length,int[] duplication) {
int start=1;
int end=length-1;
boolean result=false;
while(end>=start) {
int mid=(end-start)/2+start;
int count=countRange(numbers,length,start,mid);
if(end==start) {
if(count>1) {
result=true;
duplication[0]=start;
return result;
}
else break;
}

if(count>(mid-start+1)) end=mid;
else start=mid+1;

}
return result;
}

public static int countRange(int[] numbers, int length,int start,int mid) {
if(numbers==null) return 0;
int count=0;
for(int i=0;i<length;i++) {
if(numbers[i]>=start && numbers[i]<=mid) {
count++;
}
}
return count;
}

使用二分法,时间复杂度O(nlogn);空间复杂度O(1)

但这种方法不能保证找出所有重复的数字,如举例中的2,就无法判断。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: