位運算

Amroning發表於2024-10-27

1.遍歷二進位制位 + 記錄奇偶位

題目:奇偶位數

  • 遍歷一個數的二進位制位,記錄奇偶位1的個數:
class Solution {
public:
	vector<int> evenOddBit(int n) {
		vector<int>ans(2);
		for (int i = 0; n; i ^= 1, n >>= 1)
			ans[i] += n & 1;

		return ans;
	}
};
  • 或者是位掩碼,用16進位制的0x55555,即二進位制的010101...,直接與運算記錄對應位置1的個數:
 class Solution {
 public:
     vector<int> evenOddBit(int n) {
         const int MASK = 0x5555;
         return {__builtin_popcount(n & MASK), __builtin_popcount(n & (MASK >> 1))};
     }
 };

2.對每一個二進位制位取反

題目:數字的補數

簡化題目:對一個數num的每一個二進位制位取反,去掉前導0後輸出對應的十進位制數

思路:先求出num最高位的1,假如位置在s,然後設定一個最高位s為1,其餘位為0的數字n,即n = 1 << s,然後 n - 1 就是前 s - 1 位都為1的數字,將其與num取反後的數按位與後,就可以實現對num每一個二進位制位取反的效果(num的s位取反後肯定為0,所以不用管它)。

忘記取反運算子~的話看這裡 取反運算子

class Solution {
public:
	int findComplement(int num) {
		int s = -1;
		for (int i = 31; i >= 0; --i) {
			if ((num >> i) & 1 != 0) {
				s = i;
				break;
			}
		}

		int n = 1 << s;

		return ~num & (n - 1);
	}
};

簡單一點的取反可以看 4

3.計算二進位制位1的個數

題目:位1的個數

一個比較重要的模版,需要記下來

class Solution {
public:
	int hammingWeight(int n) {
		int ans = 0;
		
		while (n) {
			ans++;
			n &= (n - 1);
		}

		return ans;
	}
};

4.判斷一個數的二進位制位是否有相鄰的0

求一個數num的二進位制位中是否有相鄰的0,可以對num取反後求是否有相鄰的1。

假如num二進位制位有n位,先求一個n位全為1的掩碼:mask = (1 << n) - 1 ,num取反後的數x為 x = num ^ mask ,如果 (x & (x >> 1))的結果為0,則表示x的二進位制位中沒有相鄰的1,即num中沒有相鄰的0。

可以做這道題了:生成不含相鄰0的二進位制字串