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的二進位制字串