zoukankan      html  css  js  c++  java
  • 使用位操作

    见朋友出了问题,最近访问技术论坛时,大致是这样的:有一组。其中包括:N整数,除了的整数只有一次以外,其他已经出现3二级。如何找到只出现一次最快的数?

    作者的解法有点忘记了。可是这个题突然让我想起之前《编程之美》里的一道题, 和这个题的差别是其它都出现2次,仅仅有一个是出现一次。

    它的解法很巧妙。就是把全部整数进行异或运算,最后的结果就是仅仅出现一次的那个整数。由于异或会把相同的消除掉。可是这个题是出现3次。异或已经解决不了。第一想法是空间换时间,全部数中取最大值Max,然后定义一个数组int hashArr[Max],运用hash的思想。遍历全部整数进行hashArr[i]++运算。最后再找出hashArr[i]为1的,下标值就是所求的数。这个解法相同适用于其它出现N次的情况。解法时间复杂度为O(N),空间额外开销为S(MAX)

    可是我们能够继续深入分析。以32bit整数为例。假设把全部数的第i个比特位相加,假如和为sum。则会有例如以下等式:3(x1 + x2 + ... + xn) + x0 = sum (x1代表第一个数的第i个比特位的值 X0代表仅仅出现一次整数的第i个比特位的值) 从这个等式中能够看出x0的值为sum/3的余数。由于x0不是1就是0。肯定小于3。所以我们能够有例如以下的代码:

    int arr[N] = {};
    int _tmain(int argc, _TCHAR* argv[])
    {
    	int nMask = 1;
    	int nBitSum = 0;
    	int nDst = 0;
    	for (int i = 0; i < 32; ++i)	//依次推断32位
    	{
    		for (int j = 0; j < N; ++j)	 //对N个数的第i位求和
    		{
    			if (arr[j] & nMask)
    			{
    				nBitSum++;
    			}
    		}
    
    		if (nBitSum%3 != 0)		//余数不是1就是0
    		{
    			nDst |= nMask;
    		}
    
    		nMask <<= 1;
    		nBitSum = 0;
    	}
    
    	return nDst;
    }


    
    这样就把仅仅出现一次的数求出来了,并且假设其它数出现的次数是M次的话,mod M就能够了。时间复杂度是O(32*N),  空间额外开销就是几个成员变量。
    


    相比較而言还下面的算法是较好,当然,还详细介绍了情况而定。

    版权声明:本文博主原创文章,博客,未经同意不得转载。

  • 相关阅读:
    每天一个linux命令(5):rm 命令
    每天一个linux命令(3):pwd命令
    c++11之lambda表达式
    C++11之std::future和std::promise和std::std::packaged_task
    金三银四,为什么面试你总拿不到高薪?
    高并发神器 Nginx,到底该怎么学?
    好文 | MySQL 索引B+树原理,以及建索引的几大原则
    为什么 TCP 建立连接是三次握手,关闭连接确是四次挥手呢?
    Java & 架构硬核福利,速度上车!
    Intellij IDEA 阅读源码的 4 个绝技,我必须分享给你!
  • 原文地址:https://www.cnblogs.com/lcchuguo/p/4818892.html
Copyright © 2011-2022 走看看