位运算总结

位运算符

符号 解释
& 按位与
按位或
~ 按位异或
<< 左移
>> 右移

原码、补码、反码

补码=原码取反+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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章