原创 以另一种位图的思想来解决一道OJ题目

2014-8-16 14:38 2072 25 28 分类: 软件与OS 文集: OJ and Algorithm

前言:

以前所接触到的位图的思想都是以1位的形式去存储某个数出现的次数是1次还是0次。常见的例子不外乎在《编程珠玑》上的开篇例子里,1千万个数的排序统计,用1.25M的内存空间就可以达到遍历一遍输入数据而排序好的目的。这种思想是通用的么?也就是说,假如输入数据不再是0次或者1次,而是2次或者更多的时候,如何再次用上这种思想呢?请看下面题目

 

题目:

输入一个数组,数组有int类型整数若干,若有其中一个是出现一次或者两次,其他数字都是出现3次,要求在时间复杂度在O(N)上限里求出那个数字。

 

解法一

生搬硬套位图的思想,既然最多出现3次,那么我用两个bit位来存储一个数出现的个数。那么假如输入是2千万个数的时候,所需要的空间是2.5M。20亿个数的时候,需要的是250M。显然,这种思想还是不太好,虽然符合题目要求。像这样处理海量数据肯定是要被毙掉的。可以尝试着做改进,改进思路是分批处理,如面对20亿的数据,我只自定义一个1千万数的空间,2.5M,然后每次只是处理1千万的数,如果没有出现目标数,那么再处理下一个一千万的数(按照大小区分范围)。应该也算得上一种尚可的思路。

 

解法二

基于位图思想的变形,我用32个数来存储所有的数中0~31位出现的个数,然后对3取余,如果是2,证明这个数的某一个位出现过2次,依次从0位推到31位。最后相或即可。

这种解法只用到了32 * 32 bit的空间,至于时间,因为需要对每个位进行统计,需要遍历输入数据32次, 32* N,可依然是符合题目的O(N)要求。 

这种解法,在时间上应该是要比解法一耗时少一些。第一种解法需要遍历数据约210次,因为int类型最大值是21亿(假如不包括负数),那么就是210个1千万数了。

空间也少很多。无疑是比较好的。

    public static int singleNumber(int[] A) {

       int[] bitNum = new int[32];
       int values = 0;
       boolean twiceFlag = false;
       for(int i=0;i<32;i++){
           for(int j=0;j<A.length;j++){
              bitNum += A[j]>>i&1;
           }
           values |= (bitNum%3)<<i;
           if (!twiceFlag && (bitNum%3)>1) {
            twiceFlag = true; //如果出现两次
}
       }
       if(twiceFlag)values >>= 1;
       return values;
   }

 

文章评论3条评论)

登录后参与讨论

用户1826341 2015-1-16 22:37

牛逼,赞一个。

345002072_353389109 2014-9-2 19:29

嘻嘻

用户402158 2014-8-18 10:52

多谢分享~

用户1259785 2013-2-5 10:00

不错,可以多看看
相关推荐阅读
啊左不是蜗牛 2015-01-28 09:21
【博客大赛】那样的人生,看不穿
         昨晚11点跟PM姐姐聊天,问她今晚要不要加班,她回:刚刚开发哥哥陪她出来打的。。。我以为我十点半从实验室回去已经够晚了。。我脸红了。        我问她为什么不早点回去...
啊左不是蜗牛 2015-01-13 19:41
【智能手机】三个观点说说国产手机未来
在此篇文章之前还有一个各大手机品牌的总结,请点击查看。 智能手机之论英雄出处      谈手机之前换个角度,类比一下PC领域。 PC领域毛利最高的时候,国产PC一直混在低端。随着时代发...
啊左不是蜗牛 2015-01-09 17:56
【智能手机】论英雄出处
我认为,如果你不知道对手的底细,那么你就很难战胜对手。知己知彼,百战百胜。所以,我简单地说说我对这几家手机品牌的看法。个人之见,欢迎讨论。   苹果: 1976年成立,在乔布斯这样的天...
啊左不是蜗牛 2014-11-19 13:48
【博客大赛】蜗牛求职记之华为篇
1、前言说明          蜗牛是电赛出身,本科做硬件嵌入式,画板子和写C程序,然后研究生阶段是转战android,但是由于项目涉及到硬件,导师项目众多,小伙伴少,于是我也负责部分st...
啊左不是蜗牛 2014-08-15 11:57
Android 笔记之 listview 性能优化
列表显示需要三个元素, (1)listview 视图,用来显示列表的View ; (2)适配器,用来把数据映射到listView上面的 (3)数据,具体将被映射的数据,包括字符串,图片...
我要评论
3
25
关闭 站长推荐上一条 /2 下一条