位運算符
符號 | 解釋 |
---|---|
& | 按位與 |
按位或 | |
~ | 按位異或 |
<< | 左移 |
>> | 右移 |
原碼、補碼、反碼
補碼=原碼取反+1
例如,-5 二進制數-101; 原碼10000101; 反碼11111010; 補碼11111011
妙用
判斷奇偶數
左移一位相當於乘以2,右移一位相當於除以2
template<class T>
int Binary_Search(T *x, int N, T keyword)
{
int low = 0, high = N-1,mid;
while(low <= high)
{
mid = (low + high)>>1;//使用位運算代替乘除2可以提高代碼效率
if(x[mid] == keyword)
return mid;
if(x[mid] < keyword)
low = mid + 1;
else
high = mid -1;
}
return -1;
}
統計二進制數字中1的個數
相當於JAVA的Integer.bitCount()
int bitCount(int num)
{
int sum = 0;
while(num > 0)
{
sum += num &1;
num = num >>1;
}
return sum;
}
Swap交換兩個數值的函數
利用位運算可以不用開闢新空間實現交換數值功能
原理是利用異或運算的特性:任意數和自身異或結果爲0,0和任意數異或的結果還是其本身
a = a ^ b,普通的異或
b = b ^ a = b ^ a ^ b,因爲 b ^ b = 0,故 b = a ^ 0,即 b = a;
a = a ^ b ,因爲a在第一行重新賦值,所以a = a ^ b ^ a = b,完成了數值交換
void Swap(int& a, int& b)
{
a ^= b
b ^= a
a ^= b
}
尋找數據列表中只出現一次的數
有一個數據列表,只有一個數出現了1次,其餘N個數都出現了2次。如何不利用額外空間而且在O(n)時間內找到這個只出現一次的數?
還是利用異或的特性
int singleNumber(vector<int>& nums)
{
if(nums.empty()) return 0;
int res = 0;
for(int i : nums)
{
res = res ^ i;
}
return res;
}
檢查第i位是否爲1
例如要檢查數值num的第3位是否爲1,把1左移3位得到4(100),num & 4的返回值的就是結果
bool isOne(int num, int i)
{
return num & (1<<i);
}
把第i位改爲1
例如要把數值num的第3位改爲1,把1左移3位得到4(100),num | 4的返回值的就是結果
int alterOne(int num, int i)
{
return num | (1<<i);
}
另外,num|1相當於num+1;通常用num|1-1求得num最近的偶數
把第i位改爲0
例如要把數值num的第3位改爲0,把1左移3位得到4(100),num & ~4的返回值的就是結果,因爲 ~4的二進制是011
int alterZero(int num, int i)
{
return num & ~(1<<i);
}
把第i位取反
例如要把數值num的第3位取反,把1左移3位得到4(100),num ^ 4的返回值的就是結果
int alterOpposite(int num, int i)
{
return num ^ (1<<i);
}
取出一個數的最後一個1
把num左移1位後再進行異或,就會發現如果原數第i位是0,異或就變成1,否則變成0
利用二進制來枚舉子集
給定一組不含重複元素的整數數組 nums,返回該數組所有可能的子集(冪集)。
說明:解集不能包含重複的子集。
輸入: nums = [1,2,3]
輸出:[[3],[1],[2],[1,2,3],[1,3],[2,3],[1,2],[]]
vector<vector<int>> subsets(vector<int>& nums)
{
vector<vector<int>> res;
int len=(1<<nums.size());
for(int i=0;i<len;++i)
{
vector<int> cur;
for(int j=0;j<nums.size();++j)
{
if((i>>j)&1==1) cur.push_back(nums[j]);
}
res.push_back(cur);
}
return res;
}