• x去掉最后一位1:x & (x-1)

  • x只取最后一位1:x & -x


“范围与”的结果是首尾两数二进制的公共前缀

int rangeBitwiseAnd(int m, int n) {
    // "范围与"的结果是:首尾两数二进制的公共前缀
    // 因为非公共前缀一定是0xxx和1xxx的形式,存在中间数1000将这部分"范围与"清零
    while (n > m) {
        n &= n - 1; // 去掉最后1位
    }
    return n;
}

4的幂

bool isPowerOfFour(int num) {
    // 二进制仅有一个1,且这个1出现在...010101这些位
    return num > 0 && (num & (num - 1)) == 0 && (num & 0x55555555) != 0;
}

数字有效位反转

int findComplement(int num) {
    // 先找哪些是有效位
    int mask = ~0;
    while (mask & num) mask <<= 1;
    return ~mask ^ num;
}

位运算实现两数相加

int getSum(int a, int b) {
    while (b) {
        int carry = (a & b) << 1;
        a = a ^ b;
        b = carry;
    }
    return a;
}

也适用于负数,负数是补码表示。

字母变换大小写

回溯法。根据ascii表,letter^=32就变换大小写,32 == 刚好>字母数26的 2的幂。

不用比较符找两数的较大值

不用比较符,表达式ans = cond ? a : b;等价于 ans = cond * a + !cond * b

≥号的表达式cond = (a>=b) = (a-b >= 0) = sign(a-b)。当a,b异号时a-b可能溢出,sign(a-b)不能用;而a,b异号,a>0>b或a<0<b,sign(a-b)==sign(a),于是用sign(a)代替sign(a-b)。因此 cond = (a,b异号) ? sign(a) : sign(a-b),较大的数 = cond * a + !cond * b。

见ctci p476