2-BitMap算法是BitMap算法的一种扩展,核心是:每个数分配2个bit,00表示不存在,01表示出现一次,10表示出现2次,11表示多次或无意义。
一个int类型,占4个字节,在2-BitMap中可以表示16个数,表示全部int类型数据需要内存2^32*2bit=1G。时间复杂度O(n)。
经常用来解决的问题如下:
2.5亿个整数中找出不重复的整数的个数,内存空间不足以容纳这2.5亿个整数。
将bit-map扩展一下,用2bit表示一个数即可,0表示未出现,1表示出现一次,2表示出现2次及以上。或者我们不用2bit来进行表示,我们用两个bit-map即可模拟实现这个2bit-map。
分析:
每个数据分配2个bit,然后扫描这 2.5亿个整数,查看 Bitmap中相对应位,如果是 00 变 01 ,01 变 10 ,10 保持不变。所描完 事后,查看bitmap,把对应位是 01 的.
代码如下:
0x3是十六进制,在十进制中表示3
public class TwoBitMap {
//用两个bit为来标记某个元素的个数
int bNum=2;
//一个32位字节能标记多少个数
int bSize=32/bNum;
//数据范围(0到2^32内的数)
int numSize = 160000;//此处是16万,便于测试
//定义bitmap数组大小
int arraySize =(int)Math.ceil((double)numSize/bSize);
private int array[] = new int[arraySize];
/**
* 初始化BitMap
*/
public void initBitMap(){
for(int i=0;i
array[i] = 0;
}
}
/**
* 往BitMap中设置对应的数的个数
* @param x 要添加的数
* @param num 对应的个数
*/
public void set(int x,int num){
//获得bitMap的下标
int m = x >> 4;//或 int m = x /bSize;
//获得对应的位置
int n = x % bSize;
//将x对应位置上的数值先清零,但是有要保证其他位置上的数不变
array[m] &= ~((0x3<
//重新对x的个数赋值
array[m] |= ((num&3)<
// printInfo(array[m]);
}
/**
* 获取x在BitMap中的数量
* @param x
* @return
*/
public int get(int x){
int m = x >> 4;
int n = x % bSize;
return (array[m] & (0x3<> (2*n);
}
/**
* 往BitMap中添加数
* 如果x的个数大于三,则不在添加(2个bit为最多只能表示到3:00 01 10 11)
* @param x
*/
public void add(int x){
int num = get(x);
//只处理num小于3的
if(num<3) {
set(x, num + 1);
}
}
public static void main(String[] args) {
TwoBitMap test = new TwoBitMap();
test.initBitMap();
int sortArray[] = new int[]{1,4,1,32,2,6,4,2,69,9,4,185,2};
for(int i=0;i
test.add(sortArray[i]);
}
System.out.println("对BitMap中的所有数据排序:");
for(int i=0;i
if(test.get(i) !=0){
// System.out.print((i)+"出现的次数:"+test.get(i)+" ");
System.out.print(i+" ");
}
}
System.out.println("\n只出现一次的数据:");
for(int i=0;i
if(test.get(i) == 1){
System.out.print(i+" ");
}
}
}
/**
* 输出一个int的二进制数
* @param num
*/
public static void printInfo(int num){
System.out.println(num+" 二进制为"+Integer.toBinaryString(num));
}
}