位图使用

(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专门用来保存符号


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值