现有一数组int[] num存放了二百亿个正整数,数组元素是有序的(有一个数字存在重复),现用最快的方法找出数组中重复的一个数子。
本人一开始想到用二分查找,但是仔细一想,又有点迷茫了,到底该如何实现呢,求指点?
------解决思路----------------------
能想到的就是遍历一遍,有点类似选择排序,因为有序,相同的数字必然连在一起,遍历的时候每个元素和它的下个元素比较是否相同,相同就退出循环,这是比较直观的一个算法。时间复杂度O(N). 如果要更快,目前没想到。
------解决思路----------------------
比如这个元素值为N,因为这个数组是已排序的
1)二分查找到一个值为N的元素,记录这个位置为a
2)初始一个适宜的偏移量offset,在(a-offset, a-1) 和 (a, a+offset) 两个区间继续二分查N,找到位置a1,a2
3)递归2),offset可以适当调整,最后会得到元素值为N的 [am, an] 区间
------解决思路----------------------
只有一个重复,有序的话,倒还好,可以直接遍历,也可以使用递归的方式,写一个类似二分的算法,不过也需要遍历。
如果是没有序的话,就又要分连续与非连续咯,连续的话,直接相加,然后减去1--n的和就出来了。不连续的话,就得想想咯
------解决思路----------------------
就一个重复是吧:假如2亿的长度,就1~2亿-1的数值范围,全部^然后再^1~2亿-1.初步想法是这样的。你这可以
1 2 3 4 5 6 7 8 8 9
1 2 3 4 5 6 7 8 9 10
你看,一个目标数组,一个按下标递增的数组,一旦同样下标数值不同,那么就判断那个目标数值在哪,这样用你的那个二分查找可行吧,不过就效率可以很很很普通
------解决思路----------------------
有一个数字存在重复 这个条件很重要,而且数组是已经排序了的,所以你只需要比较当前这个数跟下一个输是否相等就可以了,最简单的方式就是循环
for(int i = 0; i < array.length - 1; i++){
if(array[i] == array[i+1]){
// 重复
break;
}else{
// 不重复
}
}
------解决思路----------------------
//要查的大数组
int[] a={1,3,5,6,6,8,11};
//以数组的最大数为b数组的大小
int[] b=new int[a[a.length-1]];
for(int i:a)
{
//数组默认值为0,如果赋过值就不为0了
if(b[i]!=0)
{
System.out.println("找到重复的数:"+i);
break;
}else
{
b[i]=1;
}
}
------解决思路----------------------
LZ的题目中,有几个关键字 顺序的、最快、大量元素、一个
我感觉是不是可以这样
那如果是最快,那单线程做肯定不能做到最快,所以应该用到多线程
大量元素所以需要分组,当找到一个的时候就判断就可以结束了。
如果不考虑占用机器性能,那可以数组分成一定量的的结合(可重叠),分布计算就可以保证最快
------解决思路----------------------
二分也是可以的,只要找到序号和数值不一致的分割点就好
例如 条件,这个数后面的数 序号比数值小,前面的数字,数值跟序号相同
找到这个分割点,就是要找的数字。
不过,如果,32Bits最大可以表示40亿多一点。
40/32 全部4G内存,最多可以储存大约 1 亿 数字 。
如果用位表示,可以表示4亿 数字 。
如果数据从文件读取,那么 可以用全部内存储存4亿 数字,
可以用异或运算,获取这个数据。
不过还是觉得,二分更快
如果要表示 200亿需要64Bits