位运算的具体使用

179 阅读2分钟

1 位移的妙用

 位1的个数

LeetCode191 Easy

最关键的就是  n = n & (n - 1) 这句话,首先他的作用是 是将整数 n 的二进制表示中的最后一个 1 变为 0。这个操作可以用来统计一个整数中的二进制表示中有多少个 1(也被称为 "位1的个数" 问题)


public class Solution {

    // you need to treat n as an unsigned value

    public int hammingWeight(int n) {

        // 汉明重量 hammingWeight

        int count = 0;

        while (n != 0) {

            // 这个操作会把 n 机器数的最后一个 1 给去掉

            n = n & (n - 1);

            count++;

        }

        return count;

    }

}

还有一种方式:利用 & 运算的性质 + for 循环进行遍历


public class Solution {

    // you need to treat n as an unsigned value

    public int hammingWeight(int n) {

        int count = 0;

        for (int i = 0; i < 32; i++) {

            count += (n >> i) & 1;

        }

        return count;

    }

}

比特位计数

LeetCode338 Easy

就是两个 for 循环,进行遍历,主要的还是上一题的思路


class Solution {

    public int[] countBits(int n) {

        int[] bits = new int[n + 1];

        for (int i = 0; i <= n; i++) {

            for (int j = 0; j < 32; j++) {

                bits[i] += (i >> j) & 1;

            }

        }

        return bits;

    }

}

还有其他思路,就是是使用  n = n & (n - 1);


class Solution {

    public int[] countBits(int num) {

        int[] bits = new int[num + 1];

        for (int i = 0; i <= num; i++) {

            bits[i] = countOnes(i);

        }

        return bits;

    }

  


    public int countOnes(int x) {

        int ones = 0;

        while (x > 0) {

            x &= (x - 1);

            ones++;

        }

        return ones;

    }

}

颠倒无符号整数

由于是无符号整数所以相当于简单

LeetCode190 Easy

由于可以向前移动,所以思路也不是非常复杂,而且要用 & 运算这样可以复制反转前对应的值


public class Solution {

    // you need treat n as an unsigned value

    public int reverseBits(int n) {

        int reversInt = 0, power = 31;

        while (n != 0) {

            reversInt += (n & 1) << power;

            // n 进行无符号右移动

            n >>>= 1;

            power--;

        }

        return reversInt;  

    }

}

位实现加减乘除专题

位运算实现加法

LeetCode371 Medium


class Solution {

    public int getSum(int a, int b) {

        while (b != 0) {

            // 需要进的位数

            // 如果是两个 1 那么就要进位,所以需要判断是不是两个 1 所以需要进行 & 运算,而且还需要向前移动一位

            int sign = (a & b) << 1;

            // 进行异或运算,相同为 0 不同为 1 ,非常符合加法运算,就是 如果是两个 1 那么这个位上应该是 0 ,如果是两个 0 的话那么这个位上应该也是 0 ,其他情况下就是 1

            a = a ^ b;

            b = sign;

        }

        return a;

    }

}

 递归乘法

LeetCode 面试题 08.05. 递归乘法Medium


class Solution {

    public int multiply(int A, int B) {

        int min = Math.min(A, B);

        int max = Math.max(A, B);

        int ans = 0;

        // 循环,分别将 min 不断右移(相当于除以2),同时将 max 不断翻倍

        for (int i = 0; min != 0; i++) {

            // 当 min 的二进制表示末位为 1 时,表示 min 是奇数,这时将 max 加到 ans 上

            // 当 min 是偶数的时候可以这样想:3 * 4 = (1 + 2)* 4 所以 max 就可以直接加到 ans 里面,因为有一个 1 和 max 相乘结果还是 1 的

            if ((min & 1) == 1) {

                ans += max;

            }

           

            // min 右移一位,相当于 min 除以 2

            min >>= 1;

           

            // max 翻倍,相当于 max 乘以 2

            max += max;

        }

        return ans;

    }

}