位运算骚操作

位运算骚操作

异或操作

异或运算性质

1)异或运算就是无进位相加
2)异或运算满足交换律、结合律,也就是同一批数字,不管异或顺序是什么,最终的结果都是一个
3)0^n=n,n^n=0
4)整体异或和如果是x,整体中某个部分的异或和如果是y,那么剩下部分的异或和是x^y

骚操作

  • 交换两个数
void exchange(int &a, int &b)
{
    if(a == b) return; //防止&a,&b指向同一个地址;那样结果会错误。
    a ^= b ^= a ^= b;
}
  • 不用任何判断语句和比较操作,返回两个数的最大值
// 非负数返回1 负数返回0
int sign(int n)
{
	return !(unsigned int)n >> 31;
}

void  getmax(int a, int b)
{
    // c可能溢出
    int c = a - b;
    // a的符号
    int sa = sign(a);
    // b的符号
    int sb = sign(b);
    // c的符号
    int sc = sign(c);
    // 判断A和B,符号是不是不一样,不一样就返回1, 一样就返回0
    int diffAB = sa ^ sb;
    // 判断A和B,符号是不是一样,一样就返回1, 不一样就返回0
    int sameAB = !diffAB;
    
    int returnA = diffAB * sa + sameAB * sc;
    int returnB = !returnA;
    return a * returnA + b * returnB
}
  • 找到缺失的数字

https://leetcode.cn/problems/missing-number/

class Solution {
public:
    int missingNumber(vector<int>& nums) {
        int all = 0, miss = 0;
        int size = nums.size();
        for(int i = 0; i < size; i ++ )
        {
            all ^= i;
            miss ^= nums[i];
        }
        all ^= size;
        return all ^ miss;
    }
};
  • 提取出二进制里最右侧的1
// Brian Kernighan算法
int right_one(int x)
{
    return x & (-x);  // 返回int,但是32位里只有1个位置是1,且为最右边那个
}

位运算的骚操作

  • 判断一个整数是不是2的幂
// Brian Kernighan算法
bool isPowerOfTwo(int n)
{
    return n > 0 && n == (n & -n);
}
  • 判断一个数是不是3的幂
// 如果一个数字是3的某次幂,那么这个数一定只含有3这个质数因子
// 1162261467是int型范围内,最大的3的幂,它是3的19次方
// 这个1162261467只含有3这个质数因子,如果n也是只含有3这个质数因子,那么
// 1162261467 % n == 0
// 反之如果1162261467 % n != 0 说明n一定含有其他因子
bool isPowerOfThree(int n)
{
    return n > 0 && (1162261467 % n == 0);
}

bool isPowerOfThree2(int n)
{
    while(n && (n % 3 == 0)) n /= 3;
    return n == 1;
}

  • 抹去最右边的1
n = n & (n - 1);
  • 逆序二进制的状态

https://leetcode.cn/problems/reverse-bits/

// 位运算分治
class Solution {
private:
    const uint32_t M1 = 0x55555555; // 01010101010101010101010101010101
    const uint32_t M2 = 0x33333333; // 00110011001100110011001100110011
    const uint32_t M4 = 0x0f0f0f0f; // 00001111000011110000111100001111
    const uint32_t M8 = 0x00ff00ff; // 00000000111111110000000011111111

public:
    uint32_t reverseBits(uint32_t n) {
        n = n >> 1 & M1 | (n & M1) << 1;
        n = n >> 2 & M2 | (n & M2) << 2;
        n = n >> 4 & M4 | (n & M4) << 4;
        n = n >> 8 & M8 | (n & M8) << 8;
        return n >> 16 | n << 16;
    }
};

位运算实现加减乘除

int add(int a, int b)
{
    int sumtmp = a ^ b;
    int carry = (a & b) << 1;
    while(carry)
    {
		int temp = sumtmp;
        sumtmp = temp ^ carry;
        carry = (tmep & carry) << 1;
    }
    return sumtmp;
}

int neg(int n) // 取反
{
    return add(~n, 1);
}

int minus(int a, int b)  // a - b
{
    return add(a, neg(b));
}

int multiply(int a, int b)
{
    int ans = 0;
    unsigned int c = (unsigned int)b;
    while(b != 0)
    {
		if((b & 1) != 0)
        {
			ans = add(ans, a);
        }
        a <<= 1;
        c >>= 1;
    }
    return ans;
}

int div(int a, int b)
{
    int x = a < 0 ? meg(a) : a;
    int y = b < 0 ? neg(b) : b;
    int ans = 0;
    for(int i = 30; i >= 0; i = minus(i, 1))
    {
        if((x >> i) >= y)
        {
			ans |= (1 << i);
            x = minus(x, y << i);
        }
    }
    return ((a < 0) ^ (b < 0)) ? neg(ans) : ans;
}
posted @ 2024-05-08 13:26  ihuahua1415  阅读(3)  评论(0编辑  收藏  举报
*/