这是道神题,涉及到了分治,bit操作,这里给出详细思路。
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
CODE
int odd_ones(unsigned x) { x^=x>>1; x^=x>>2; x^=x>>4; x^=x>>8; x^=x>>16; return x&1; }
分析
x^=x>>1; (xm.n是 xm xor xn)(自己画的图片,不对齐,见谅)
x^=x>>2
x^=x>>4
x^=x>>8
x^x>>16
相信大家已经发现规律了
每进行一次,x第一个bit 异或多了一倍从 1 -> 2 -> 4 -> 8 -> 16 -> 32。从而实现了每一位的xor,并将结果放在了x的第一个bit。
接着,有些人可能不明白为什么要xor,xor的作用是什么。
要知道xor的在这个题目里发挥的作用,先看真值表
如果两位都是0,或都是1,那么证明这个数里有2个0或者2个1(有点废话hehe),那么这个数bit是奇还是偶不由这二位决定。
如果两位是1 0,或者 0 1 ,那么证明这二个bit排列的结果是奇。所以可以直接用1来代替这两bit。(感觉这里我解释的不是很清楚,见谅哦)
经过上面的分析,得到:x第一个bit放着32位bit的异或。如果是 0 0,或者1 1,变为0(奇偶不用决定),如果是1 0 ,或者0 1,变为1(将两位化为一位).最后x第一个bit就能决定该数里有偶数个1还是奇数个了。
结语
最后说一点:为什么有分治的思想呢,因为可以这么想:先判断XnXn-1这两个bit里bit位为1是奇还是偶,是奇,变为1
是偶数,变为0.
再判断Xn+2Xn+1 XnXn-1,此时Xn+2Xn+1 XnXn-1进过上一步,都是一bit
这样便是分治的思想了。
append:
不敢相信,在2.66,也用到了这种思路。
/*Generate mask indicating leftmost 1 in x.Assume w=32. **/同样,先给出代码
int leftmost_one(unsigned x) { x|=x>>1; x|=x>>2; x|=x>>4; x|=x>>8; x|=x>>16; return x^(x>>1); }
哇,超眼熟的,有了上面的思路,这题当然也轻车熟路啦
x|=x>>1(2)(4)(8)(16)
x第一个bit与前面所有bit或
x第二个bit与前面所有bit或
。。。。。。
x第31个bit与第32个bit或
x第32个bit与0个bit或
这样,就能将x转换为[00000..........111111111111]也就找到了最高位。
总结
我认为:这应该是一种bit的算法,但是我不知道叫什么,总结为:
如果op是&,?????
如果op是|,找最高位
如果op是^,bit中1的0数量是奇还是偶
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
reference:
https://blog.csdn.net/zhanyu1990/article/details/24936663
http://www.matrix67.com/blog/archives/264
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
如果通过我的文章理解了,就给个打赏个赞,如果还有疑问,可以发邮件和我讨论 peanwang @outlook.com,或者[email protected]