leetcode每日一题系列-二进制中1的个数

324 阅读3分钟

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

leetcode-剑指offer【15】-二进制中1的个数

[博客链接]

一个菜🐔的学习之路

掘金首页

[题目描述]

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



 示例 1: 


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


 示例 2: 


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


 示例 3: 


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



 提示: 


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




 注意:本题与主站 191 题相同:https://leetcode-cn.com/problems/number-of-1-bits/ 
 Related Topics 位运算 
 👍 131 👎 0

[题目链接]

leetcode题目链接

[github地址]

代码链接

[思路介绍]

思路一:暴力法+位运算

  • 通过判断 n & 1 == 1 判断末位是否为1
  • 然后无符号右移即可
  • 这个的测试用例真的挺奇怪的居然偶尔会TLE
public int hammingWeight(int n) {
    int res = 0;
    while (n != 0) {
        if ((n & 1) == 1) {
            res += 1;
        }
        n >>>= 1;
    }
    return res;
}

**时间复杂度O(k)**k最大32


思路二:java.Integer库的调用

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

时间复杂度O(logk)k最大32


思路三:位运算的奇思妙想

  • n &= (n-1) 会将最后位1变成0
  • n-1表示把最后一位的1右边全变成1,当前位变为1,然后与n与运算则表示当前位右侧以及当前位都变成0
  • 计算次数则为1的个数

WechatIMG246

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

时间复杂度O(k)-主要优化的是删除了中间为0的运算


思路四:思路一的多种写法

  • 虽然我也没看出来啥优化
public int hammingWeight(int n) {
            int ret = 0;
            for (int i = 0; i < 32; i++) {
                if ((n & (1 << i)) != 0) {
                    ret += 1;
                }
            }
            return ret;
        }

时间复杂度O(k),可能是leetcode更信任常量?


思路五:思路一的多种写法

public int hammingWeight(int n) {
            int res = 0;
            while (n != 0) {
                res += (n & 1);
                n >>>= 1;
            }
            return res;
        }

时间复杂度O(k)


思路六-logk写法

  • 这个是java库的写法
  • 手写了一次运算过程

image-20210623113311422

简化后运算过程

image-20210623113321468

public int hammingWeight(int i) {
    // HD, Figure 5-2
    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;
}

这种做法没有宫水三叶 题解中的具有通用性

public int hammingWeight(int n) {
        n = (n & 0x55555555) + ((n >>> 1)  & 0x55555555);
        n = (n & 0x33333333) + ((n >>> 2)  & 0x33333333);
        n = (n & 0x0f0f0f0f) + ((n >>> 4)  & 0x0f0f0f0f);
        n = (n & 0x00ff00ff) + ((n >>> 8)  & 0x00ff00ff);
        n = (n & 0x0000ffff) + ((n >>> 16) & 0x0000ffff);
        return n;
    }

时间复杂度O(logk)k最大32

这做法我印象里做过,但是具体忘记了哪道题了后续会补