(1)排序
1.问题描述
给定大量正整数,互不相等,对这些正整数进行排序,要求时间复杂度为O(n)
2.分析
一般的排序时间复杂度都达不到O(n),如果数据量比较小,可以使用基数排序。由于此处数据量比较大,所以使用位图。具体而言,假如要对数组 [5, 2, 12, 18, 7, 9, 13, 19, 16, 4, 6] 进行排序(最大值不超过20), 则可以将其映射到位串 1101 0011 0010 0111 0100 ,其中, 1 表示数组元素出现的位置(最高位在后面,最低位在左边,以下标0起头),然后,从低位往高位扫描, 即可得到 { 2, 4, 5, 6, 9, 12,13,16,18,19} 这样就排序好了。
3.代码
int[] a = {5, 2, 12, 18, 7, 9, 13, 19, 16, 4, 6};
int max = 20;
int[] bits = new int[((max-1)>>5)+1];
for(int i=0; i<a.length; i++)
{
int pos = a[i]>>5;
int offset = a[i]&((1<<5)-1);
bits[pos] = bits[pos] | (1<<offset);
}
for(int i=0; i<=max; i++)
{
int pos = i>>5;
int offset = i&((1<<5)-1);
if(1==(bits[pos]>>offset & 1))
System.out.print(i+" ");
}
结果为:
2 4 5 6 7 9 12 13 16 18 19
4.注意
1>因为是使用索引来标记值,所以数组中不能有负数
2>因为是使用索引来标记值,所以如果其中有重复值,则上述方法需要更改
3>如果不确定最大值。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
(2)统计数据中的不重复(或重复)数据的个数
1.问题描述
给定大量整数,可能有重复数字,统计其中仅出现一次的数据
2.分析
使用2个bitset,默认时候两个bitset全为0,一个数字第一次出现时,分别在其中设置为1-0,第二次出现时设置为1-1,以后再出现不更改就可以了。当设置结束时,如果要找仅出现一次的元素,那么就找两个bitset设置为1-0的元素即可。
3.代码
int[] a = {5, 2, 12, 18, 7, 9, 13, 19, 16, 4, 6,5,2};
int max = 100;
long[] bits = new long[((max-1)>>6)+1];
long[] repeat = new long[((max-1)>>6)+1];
int pos = 0;
long offset = 0;
for(int i=0; i<a.length; i++)
{
pos = a[i]>>6;
offset = a[i]&((1L<<6)-1);
if(((bits[pos]>>offset) & 1L) == 1)
{
if(((repeat[pos]>>offset) & 1) == 0)
repeat[pos] = repeat[pos] | (1L<<offset);
}
else
bits[pos] = bits[pos] | (1L<<offset);
}
for(int i=0; i<=max; i++)
{
pos = i>>6;
offset = i&((1L<<6)-1);
if(((bits[pos]>>offset)&1)==1 && ((repeat[pos]>>offset)&1)==0) //寻找只出现一次的元素
System.out.print(i+" ");
}
结果为:
4 6 7 9 12 13 16 18 19
4.注意
1>像这种需要使用bitset的情况,最好将bitset设置为class,这样就可以不用重复定义
2>如果其中有负数,那么可以再增加一个bitset专门用来保存符号