使用Java,我必须创建一个程序,它接受一组有序的数字并返回最长的连续数字序列的长度。例如,对于集合(1,18,12,6,8,7,13,2,3,4,9,10),该方法应返回5,因为最长的连续序列是(6,7,8,9) ,10)。
它应该尽可能高效,你不能使用散列图,实际上只是迭代我猜测最好的选择是对数组进行排序(nlogn),然后再次运行数组( n)将是最好的选择吗?
答案 0 :(得分:1)
如果您有如此大的输入以致O(n log n)算法太慢并且您想要一个不使用hashmap的算法,则可以使用基数排序并仍然获得相同的O(n)性能。
基数排序:http://en.wikipedia.org/wiki/Radix_sort
基本上它通过在最低k(我通常使用4或8)位,然后在下一个最低k位上应用桶排序来对输入进行排序,依此类推,直到所有位都被排序为止。
代码如下所示(对不起,我不熟悉Java,所以它可能包含一些错误,但我希望你能理解我的意思。)
static final int RADIX_POW2=4;//you could also use 8 if you want it
//twice as fast and 16 times as space taking.
static final int RADIX=1<<RADIX_POW2;
static void radix_sort_part(int[] input, ArrayList<int>[] buckets, int shift){
for(int x:input) buckets[x>>shift & (RADIX-1)].add(x);
int count=0;
for(ArrayList<int> bucket:buckets){
for(int x:bucket)
input[count++]=x;
bucket.clear();
}
}
static void radix_sort_full(int[] input){
ArrayList<int>[] buckets=new ArrayList<int>[RADIX];
for(int i=0;i<RADIX;i++)
buckets[i]=new ArrayList<int>();
//I'm performing radix sorts on full 32 bits, but if the range of
//your inputs are smaller, you only need to perform it on the range.
for(int i=0;i<sizeof(int)*8/RADIX_POW2;i++)
radix_sort_part(input,buckets,i*RADIX_POW2);
}
static int find_max_consecutive(int[] input){
radix_sort_full(input);
int maxconsecutive=1;
int currentconsecutive=1;
for(int i=1; i<input.size();i++){
if(input[i]=input[i-1]+1)currentconsecutive++;
if(currentconsecutive>maxconsecutive)maxconsecutive=currentconsecutive;
}
return maxconsecutive;
}
但是,如果您有许多相对较小的输入并且需要一次又一次地解决此问题,我认为此算法很慢。 对于大量输入,此算法可能与hashmap一样耗费内存,而不是那么快。因此,如果我被要求选择,我宁愿使用hashmap。
修改强> 我忘了提到基数排序花费的时间与执行桶排序的次数成正比,即((整数的位数)/ RADIX_POW2)。 因此,该算法的确切时间复杂度为O(dn),其中d为(整数的位数)/ RADIX_POW2。 这意味着如果你想将算法用于长数,它需要两倍的时间,如果你想将它用于BigInteger或String或类似的东西,那么整数(字符串)的大小就会花费。