leetcode-notebook
@ JunJian Feng | 星期四,三月 19 日,2020 年 | 2 分钟阅读 | 更新于 星期四,三月 19 日,2020 年

位运算

  • 与 int&1
// 4 & 1
4 ==> 100
1 ==> 001
& ==> 000 ==> (int)0
.......*
// 3 & 1
3 ==> 11
1 ==> 01
& ==> 01  ==> (int)1
// 128 & 2
128 ==> 10000000
2   ==> 00000010
&   ==> 00000000  ==> (int)0
  • “10000” & “1000”
"10000" & "01000" ==> "00000"
  • 或 (计算优先级低)
"10000" | "01000" ==> "11000"
  • 右移 »
26 >> 2 ==> "11010" >> 2 ==> 110 ==> (int)6
  • 左移 «
26 << 2 ==> "11010" << 2 ==> 1101000 ==> (int)104
  • 取反 ~ (计算优先级高)

负数是用补码表示的,补码是原码取反+1

~26 ==> -27
26  ==> 0.....0 11010 // 32位或64位
~26 ==> 1.....1 00101 // 32位或64位 补码
........*             // 补码 第一位0正1符        -
        1.....1 00100 // 原码取反
        0.....0 11011 // 原码 bindec("11011") ==> 27

~26 ==>                                          -27
  • 异或 ^

一个为 1 另一个为 0 的位设为 1

26^27

26 ==> 11010            128 ==> 10000000
27 ==> 11011            127 ==> 01111111

^  ==> 00001            ^   ==> 11111111
       (int)1                   (int)255
  • 位运算分治

leetcode 190.颠倒给定的32位无符号整数的二进制位

    $m1 = 0x55555555 // 01010101010101010101010101010101 // 一个一组
n=26         ==>        00000000000000000000000000011010
    n>>1     ==>        00000000000000000000000000001101
(n>>1) & $m1 ==>        00000000000000000000000000000101     5

    n&$m1    ==>        00000000000000000000000000010000     16
(n&$m1) << 1 ==>        00000000000000000000000000100000     32

step1                   00000000000000000000000000100101  ==> 37
    $m2 = 0x33333333 // 00110011001100110011001100110011 // 两两一组
n=37         ==>        00000000000000000000000000100101
    n>>2     ==>        00000000000000000000000000001001      10
(n>>2) & $m2 ==>        00000000000000000000000000000001      1

    n&$m2    ==>        00000000000000000000000000100001      33
(n&$m2) << 2 ==>        00000000000000000000000010000100      132

step2        ==>        00000000000000000000000010000101      133
    $m4 = 0x0f0f0f0f // 00001111000011110000111100001111 // 四个一组
n=133        ==>        00000000000000000000000010000101
    n>>4     ==>        00000000000000000000000000001000      8
(n>>4) & $m4 ==>        00000000000000000000000000001000      8

    n&$m4    ==>        00000000000000000000000000000101      5
(n&$m4) << 4 ==>        00000000000000000000000001010000      80

step3        ==>        00000000000000000000000001011000      88
    $m8 = 0x00ff00ff // 00000000111111110000000011111111 // 八个一组
n=88        ==>         00000000000000000000000001011000
    n>>8     ==>        00000000000000000000000000000000
(n>>8) & $m8 ==>        00000000000000000000000000000000

    n&$m8    ==>        00000000000000000000000001011000      88
(n&$m8) << 8 ==>        00000000000000000101100000000000

(n >> 8) & $m8 | (n&$m8) << 8
step4        ==>        00000000000000000101100000000000      ==> 22528
             ==>        00000000000000000000000000000000
             ==>        01011000000000000000000000000000

step5        ==>        01011000000000000000000000000000      1476395008
n=26         ==>        00000000000000000000000000011010

原理 1234 5678

1234 5678
1001 0101

step1
1234  01            5678 01
      01                 05
      20                 60
      21                 65

        03                 07
        40                 80
        43                 87

      2143               6587
step2
2143  0011          6587 0011
      0021               0065
      4300               8700
      4321               8765
step3
43218765    00001111
            00004321
            87650000
            87654321

8765 4321

step1具体:

12345678
10010101

12345678 >> 1 ==> 01234567 ==> 01001010 ==> 01001010 & 01010101 ==> 01000000
12345678 ==> 10010101 & 01010101 ==> 00010101 ==> 00010101 << 1 ==> 00101010

    01000000
    00101010
    01101010  // step1实际结果
    --------
    12345678
    10010101
    --------
    21436587
    01101010  // step1预计
    --------