您的位置:首页 > 理论基础 > 数据结构算法

数组8:数组中重复的数字

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

思路:要对数组查找重复的数字是一个比较常见的问题。注意,这里只要随便找出一个重复发的数字即可,不用找出全部重复数字;而且这里有一个条件,就是数组中的所有数字都在0到n-1的范围之内。要根据这个特性寻找解决方法。

方法一:通用方法,将数组进行排序O(nlogn),然后遍历数组,计算每个数字出现的次数即可找出所有重复的数字以及确定重复的次数,即转化为一个排序的问题。

方法二:使用散列hash表,理解,hash表的本质就是一个数组,数组有下标和值这两个属性。对于需要分配的数据,需要根据一个散列函数,将数据散列到不同的数组位置上面去,数据必须有一个key和value,根据他的key的hashcode或者其他数值去散列数组中找对应下标的位置,即数据的key的hashcode对应的是散列数组中的下标;散列有一个问题就是当多个数据根据散列函数分配到同一个数组下标位置时,会造成覆盖,于是使用分离链接法在数组每个元素中又创建了一个链表,相同的元素放在这个链表上面。本题中由于只需要记录一下数据在hash表中的出现次数不需要存放具体的数据对象,因此不需要使用链表,直接使用一个数组就可以。即创建一个数组b[],遍历a[]的每个元素时,根据a[i]的值去b[]中下标j=a[i]的位置查找b[a[i]]是否为0,0表示不存在,设为1,1表示已经出现过一次,再次出现就表示重复了。即时间复杂度为O(n),空间复杂度为O(n)

方法三:使用一种巧妙的方法,已知大小为n的数组中的元素值都在0~n-1之间,如果元素没有重复那么排序后位置i与元素值之间应该一一对应,即调整顺序后a[0]=0;a[1]=1;a[2]=2;

a[3]=3……因此当我们遍历数组并按照a[i]==i的准则判断调整数组,每次调整可以使得一个元素到达正确位置,于是最多调整n次就可以使得全部元素到达正确的位置,如果存在重复的数字,那么在调整的过程中间必然会出现a[i]的值与要调整到的位置的值a[a[i]]重复的情况,即发生了重复。时间复杂度O(n),空间复杂度O(1)

//理解:由于数组是引用传递,因此调用duplicate方法时传入一个数组duplication,在方法中对他进行赋值后他原来的数组对象就会相应改变

public boolean duplicate(int numbers[],int length,int [] duplication) {
//特殊的输入: 空输入是测试案例会检测的,必须解决
if(numbers==null||numbers.length<=0) return false;

/*要判断条件不满足的情况:长度不匹配:这个判断剑指offer上面有,最好有,看测试平台的理解
if(numbers.length!=length) return false;
//数组值不在0~n-1的范围之内
for(int i=0;i<numbers.length;i++){
if(numbers[i]<0||numbers[i]>numbers.length-1) return false;
}
*/
//遍历数组,不断调整数组到a[i]==i的状态
for(int i=0;i<numbers.length;i++){
while(numbers[i]!=i){
//位置不合理时,需要调整到目标位置,先判断与目标位置的值是否相同重复
if(numbers[i]==numbers[numbers[i]]){
duplication[0]=numbers[i];
return true;
}else{
//与目标位置不重复,交换位置
int temp=numbers[numbers[i]];
numbers[numbers[i]]=numbers[i];
numbers[i]=temp;

}
}
}
//循环结束还没有重复,说明没有重复
return false;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐