题目
LCR 133. 位 1 的个数
编写一个函数,输入是一个无符号整数(以二进制串的形式),返回其二进制表达式中数字位数为 ‘1’ 的个数(也被称为 汉明重量).)。
提示:
请注意,在某些语言(如 Java)中,没有无符号整数类型。在这种情况下,输入和输出都将被指定为有符号整数类型,并且不应影响您的实现,因为无论整数是有符号的还是无符号的,其内部的二进制表示形式都是相同的。
在 Java 中,编译器使用 二进制补码 记法来表示有符号整数。因此,在上面的 示例 3 中,输入表示有符号整数 -3。
- 示例 1:
输入:
n = 11
(控制台输入00000000000000000000000000001011
)
输出:3
解释:输入的二进制串00000000000000000000000000001011
中,共有三位为 ‘1’。
- 示例 2:
输入:
n = 128
(控制台输入00000000000000000000000010000000
)
输出:1
解释:输入的二进制串00000000000000000000000010000000
中,共有一位为 ‘1’。
- 示例 3:
输入:
n = 4294967293
(控制台输入11111111111111111111111111111101
,部分语言中n = -3
)
输出:31
解释:输入的二进制串11111111111111111111111111111101
中,共有 31 位为 ‘1’。提示:
输入必须是长度为 32 的 二进制串 。
注意:本题与主站 191 题相同:https://leetcode-cn.com/problems/number-of-1-bits/
思考
- 这道题直接使用循环右移依次判断是最直观的想法,而且由于最多只有32位,也就是循环32次而已,时间复杂度很低
- 那有没有什么方法可以有几个1就判断多少次,而不额外判断0,使用下面这种解法就可以做到
解法
- 思想:从最右边的1开始,每次都消去一个1
- 当 n-1 时,可以让一个数最右边的 1 变成 0,而且这个 1 右边的 0 都变成 1(10101000 -> 10100111)
- 此时使用 n & n-1,可以让这个 n 最右边的 1 变成 0,而且由于这个 1 已经是 n 最右边的 1 了,所以这个 1 的右边都是 0,此时与上 n-1,虽然 n-1 将 n 最右边的 1 右边的 0 都变成了 1,但是与上 n 后这些 1 都无法起作用
- 最终相当于消去了 n 最右边的 1,有几个 1 就执行几次操作,比起直接循环少了对 0 位的判断
图片来自:https://leetcode.cn/leetbook/read/illustration-of-algorithm/5vgz7m/
class Solution {
public:
int hammingWeight(uint32_t n) {
int ans=0;
while(n){
n&=n-1;
ans++;
}
return ans;
}
};