位运算

yuyu888 于 2020-12-31 发布

序言

位运算是计算机的基础, 熟练使用位运算,将极大的扩展我们的思路和眼界,也可以提高算法的计算效率降低系统开销;

位运算基础

题解

判断两个数是否相同

!(num1 ^ num2)

判断偶数

!(num & 1)

判断num是否是2的n次方

!(num & (num - 1))
一个数如果是2的n次方,那么它的二进制只有1个1,比如10, 100, 1000,这个数减1是01, 011, 0111,这样相与必然等于0,这就是!(num & (num -1))的判断, 有一个例外情况是0,0不是2的幂,但它和任意数与都为0,所以应该将它排除在外,所以最严谨的公式
num && (!(num & (num - 1)))

bit串截取

num&( (1<<len) - 1 )

异或加密

异或加密是一个很简单且速度很快的算法,它利用了xor的这个特性:A ^ B ^ B = A,其中A是明文,B是密钥。

为什么这个等式能成立呢,因为异或的两个规律:

现在我们来推导这个过程:

A ^ B ^ B = A ^ (B ^ B) = A ^ 0 = A

演算

A=17 B=5

17^5=20

10001 ^ 00101 = 10100

20^5=17

10100 ^ 00101 = 10001

位图(bitmap)运算

假如我们有一组数字:2,3,7,8 我们把存入到集合set里;set初始值设为0;

    set = set | (1 << (num-1))

    例如:

    插入 2 :set = 0 | (1 << (2-1) ) = 10

    插入 3 :set = 10 | ( 1 << (3-1) ) = 110

    插入 7 :set = 110 | ( 1 << (7-1) ) = 100 0110

    插入 8: set = 100 0110 | ( 1 << (8-1) ) = 1100 0110
    set = set ^ (1 << (num-1)) 

    例如:

    删除 7 :1100 0110 ^ (1 << (7-1)) = 1100 0110 ^ 0100 0000 = 1000 0110 

    当 num 确实存在于set中时, 上述表示时正确的, 最正确的表示方法

    set = set & (~(1 << (num-1)))

    set & (1 << (num-1)) 

    例如:

    是否存在 7 : 1100 0110 & (1 << (7-1)) = 1100 0110 & 0100 0000 = 0100 0000 

    是否存在 6 : 1100 0110 & (1 << (6-1)) = 1100 0110 & 0010 0000 = 0000 0000 => 0
    !(( set1 & set2 ) ^ set2)
  
    演算:

    【例1】

    set1 初始化为 { 2,3,7,8 } 的集合 1100 0110

    set2 初始化为 { 2, 3 }      的集合 0000 0110

    则 !((1100 0110 & 0000 0110) ^ 0000 0110) = !(0000 0110 ^ 0000 0110) = !(0000 0000) 

    【例2】

    set1 初始化为 { 2,3,7,8 } 的集合 1100 0110

    set2 初始化为 { 2, 4 }      的集合 0000 1010

    则 !((1100 0110 & 0000 0110) ^ 0000 1010) = !(0000 0010 ^ 0000 1010) = !(0000 1000)