LeetCode刷题笔记 ~ 剑指 Offer 15. 二进制中1的个数

186 阅读4分钟

这是我参与更文挑战的第9天,活动详情查看:更文挑战

剑指 Offer 15. 二进制中1的个数

请实现一个函数,输入一个整数(以二进制串形式),输出该数二进制表示中 1 的个数。例如,把 9 表示成二进制是 1001,有 2 位是 1。因此,如果输入 9,则该函数输出 2。

示例

输入:00000000000000000000000000001011
输出:3
解释:输入的二进制串 00000000000000000000000000001011 中,共有三位为 '1'。

输入:00000000000000000000000010000000
输出:1
解释:输入的二进制串 00000000000000000000000010000000 中,共有一位为 '1'。

输入:11111111111111111111111111111101
输出:31
解释:输入的二进制串 11111111111111111111111111111101 中,共有 31 位为 '1'

提示

  • 输入必须是长度为 32 的 二进制串 。

个人思路解析

方式一:逐位计算

由于要计算的是二进制,那么我们就需要用到 & 运算符的特性了

  • 1 & 1 = 1
  • 0 & 1 = 0 通过n & 1的运算,可以累加得到数字 n1的数量

代码

public class Solution {
    public int hammingWeight(int n) {
        int res = 0;
        // 终止条件
        while(n != 0){
            // 累加 n 最后一位数值
            res += n & 1;
            // 右移一位
            n >>>= 1;
        }
        return res;
    }
}

提交结果

image.png

方式二:逐位运算优化

在方式一中,我们需要对数字n的二进制每一位数值都进行一个比较,这样在时间上的开销会比较大,我们可以运用n & (n - 1)这个公式,来实现一个性能的优化,该公式可以将数值n最右边的一个1转换为0,这样我们就可以跳过中间连续为0的部分了

  • n: 100100
  • n - 1: 100011(二进制中减一,会将最右边的1变为0,后续的0变为1
  • n & (n - 1): 100000(再通过 & 运算符,将两边不同时为1的数字清0

代码

public class Solution {
    public int hammingWeight(int n) {
        int res = 0;
        while(n != 0){
            n &= (n - 1);
            ++res;
        }

        return res;
    }
}

提交结果

image.png

方式三:Integer.bitCount()

这个是java自带的一个方法,底层源码为:

public static int bitCount(int i) {
    i = i - ((i >>> 1) & 0x55555555);
    i = (i & 0x33333333) + ((i >>> 2) & 0x33333333);
    i = (i + (i >>> 4)) & 0x0f0f0f0f;
    i = i + (i >>> 8);
    i = i + (i >>> 16);
    return i & 0x3f;
}

十六进制转换为二进制

  • 0x55555555:01010101010101010101010101010101(以“1位元素”为单位,奇数为1)
  • 0x33333333:110011001100110011001100110011(以“2位元素”为单位,奇数为1)
  • 0x0f0f0f0f:1111000011110000111100001111(以“4位元素”为单位,奇数为1)

这里采用的是一个类似分治的思想,先以“1位元素”为单位,累加其中1的数量,得到的结果再以“2位元素”为单位,继续累加,重复计算,直至十六位(32位)。

拿到结果之后,再与0x3f做一个运算,确定最终1的个数。(0x3f:00111111 = 63)

代码

public class Solution {
    public int hammingWeight(int n) {
        return Integer.bitCount(n);
    }
}

提交结果

image.png