Bit Manipulation Notes

update Jan 13,2018 13:18

1. Power of Two

判断一个数是不是 2 的乘方,只要判断其二进制表示中有几个 1 即可:

第一种实现

class Solution(object):
    def isPowerOfTwo(self, n):
        """
        :type n: int
        :rtype: bool
        """
        if n <= 0:                 # 先特判 0 和 负数,然后计数 1 的个数
            return False           # 如果 1 的个数大于 1,直接返回 False
        numberOfOne = 0
        while n > 0:
            numberOfOne += n & 1
            n >>= 1
            if numberOfOne > 1:
                return False
        return True

第二种实现 (更快)

class Solution(object):
    def isPowerOfTwo(self, n):
        """
        :type n: int                      # 例如 16:0b0001 0000 
        :rtype: bool                      #   16-1 =  0000 1111
        """                               # 只要是二的乘方,则一定满足 n & (n-1) == 0
        return False if n <= 0 else n & (n - 1) == 0

2. Count the Number of Bits That Are Different

leetcode: Hamming Distance
只要 countBit(a ^ b) 就可以了。xor 可以得到所有两个数不同的位都为 1 的一个数,然后计算这个数中 1 的个数。

3. Determine If a String Contains Unique Characters

之前的思路是用一个HashSet,或者用一个 int[26]。用 bit manipulation 的思路,也可以直接用一个 int 的每个 bit 来表示一个字母。如果所面对的不只是26长度的字母,而是长度为256的ASCII码,则可以用一个 int[8] bitVector, 相当于把 256 个 bit 分成 8 个 group,每个 integer 代表 32 个 bits;

    // 判断输入 word 是否只包含 unique 的 ASCII 字符。
    public class Solution {
      public boolean allUnique(String word) {
        int[] bitVector = new int[8];
        for (char c : word.toCharArray()) {
          int group = c / 32;
          int index = c % 32;
          if ((bitVector[group] >> index & 1) == 1) return false;
          else bitVector[group] |= (1 << index);
        }
        return true;
      }
    }

4. Reverse Integer

LeetCode: Reverse Bits
两种思路,一种是用两个指针指向左右,如果左右不同则建一个只有这两位为 1 的 mask,然后与其 xor,例如:

    input:                1001 0110
    对于第 0 位和 -1 位:    l->   <-r
    两位不同,生成mask:     1000 0001
    XOR:                  0001 0111
    然后 l 和 r 向中间逼近

另一种思路是使用 divide & conquer 的思路,左右16位换位,然后每边左右8位换,然后每边4位换,然后每边2位换,这样时间复杂度 O(log32) = 5 更快;

public class Solution {
    // you need treat n as an unsigned value
    public int reverseBits(int n) {
        n = ((n & 0xffff0000) >>> 16) | ((n & 0x0000ffff) << 16); 
        n = ((n & 0xff00ff00) >>> 8) | ((n & 0x00ff00ff) << 8); 
        n = ((n & 0xf0f0f0f0) >>> 4) | ((n & 0x0f0f0f0f) << 4);
        n = ((n & 0xcccccccc) >>> 2) | ((n & 0x33333333) << 2);
        n = ((n & 0xaaaaaaaa) >>> 1) | ((n & 0x55555555) << 1);
        return n;
    }
}

results matching ""

    No results matching ""