1. 程式人生 > >[LeetCode] 476.Number Complement 備忘

[LeetCode] 476.Number Complement 備忘

476. Number Complement

Given a positive integer, output its complement number. The complement strategy is to flip the bits of its binary representation.

Note:

  1. The given integer is guaranteed to fit within the range of a 32-bit signed integer.
  2. You could assume no leading zero bit in the integer’s binary representation.

Example 1:

Input: 5
Output: 2
Explanation: The binary representation of 5 is 101 (no leading zero bits), and its complement is 010. So you need to output 2.

Example 2:

Input: 1
Output: 0
Explanation: The binary representation of 1 is 1 (no leading zero bits), and its complement is 0. So you need to output 0.

求一個數字的補數,即除了高位的0,所有位上面的值相反的數字。

最容易想到的方法就是如何得到一個mask,讓這個數的前面的幾位高位全是0,後面的低位都是1,這樣直接按位取反這個數之後和這個mask做一次位與操作就可以得到正確的結果了。所以首先讓mask為0xffffffff(題目中有32位長度的限制),之後以mask & 這個數不為0為迴圈條件,將mask一次一次的左移一位,這樣就將這個數右邊所有的位都成為0,將mask按位取反之後,得到之前我們所需要的那個mask,這樣即可求得這個數的補數。

class Solution {
public:
    int findComplement(int num) {
        int mask = ~0;
        
        while (num & mask)
        {
            mask <<= 1;
        }
        
        return ~mask & ~num;
    }
};
還有一個巧妙的方法,以2為底計算這個數的對數,轉換為整型。以該值將1向左位移,然後減去1,作為mask。與這個數按位取反之後做位與操作得到結果。對於這個方法我的理解是,比如5的二進位制為101,log2(5)的結果轉換為整型是2,1左移2位,即為4,減去1為3,3的二進位制為11,以該值作為mask可以得到正確的結果。同理我們發現6和7,二進位制分別為110和111遵循相同的規律,即處於2^2和2^3之間,就是處於二進位制1000和100之間,這些數字二進位制的開頭永遠是第三位上的1,所以如果我們可以得到第二位置和第一位的值都是1的mask,就可以輕鬆算出這些數字的補數,同理其他的數字也是如此。
class Solution {
public:
    int findComplement(int num) {
       return ~num & ((1 <<(int)log2(num))-1);
    }
};