LeetCode - 191. Number of 1 Bits
在算法的世界里,我们常常会遇到各种有趣且富有挑战性的问题。今天,让我们聚焦于 LeetCode 上的第 191 题 ——“Number of 1 Bits”,深入探讨如何高效地解决这类问题。
1. 问题描述
题目要求我们编写一个函数,输入是一个无符号整数(以二进制串的形式),函数需要返回其二进制表达式中数字位数为 ‘1’ 的个数。这就好比我们拿到一个由 0 和 1 组成的二进制串,要做的是仔细数一数其中 1 的个数。例如,输入的无符号整数转换为二进制后是 1011,那么函数应该返回 3,因为这个二进制串中有 3 个 1。
2. 解题思路(位运算)
2.1 关键点:取二进制位
位运算在解决这类问题时发挥着关键作用。我们知道,计算机在存储数据时,是以二进制的形式进行的。而位运算允许我们直接对这些二进制位进行操作,这使得我们能够高效地处理与二进制相关的问题。
2.2 解题步骤:
- a. 遍历数字每一位:我们需要一种方法来依次检查二进制数的每一位。这里,我们可以利用循环来实现对每一位的遍历。
- b. 统计 1 的个数:在遍历每一位的过程中,我们要判断当前位是否为 1。如果是 1,就将计数器加 1。
下面是使用 JavaScript 和 Python 实现的代码示例:
2.3 JavaScript
/**
* 位运算取位
* @param {number} n - a positive integer
* @return {number}
*/
var hammingWeight = function (n) {
let count = 0;
while (n) {
count += n & 1;
n = n >>> 1;
}
return count;
};
在这段 JavaScript 代码中,我们定义了一个变量count
用于统计 1 的个数。通过while
循环,只要n
不为 0,就继续循环。在每次循环中,使用n & 1
来判断n
的最低位是否为 1,如果是则将count
加 1。然后通过n = n >>> 1
将n
无符号右移一位,继续检查下一位。
2.4 Python
class Solution:
def hammingWeight(self, n: int) -> int:
count = 0
while n:
# 注意运算优先级
count = count + (n & 1)
n = n >> 1
return count
Python 代码的思路与 JavaScript 类似。在Solution
类中定义了hammingWeight
方法,同样使用count
变量统计 1 的个数。while
循环中,通过n & 1
判断当前位是否为 1 并更新count
,然后通过n = n >> 1
将n
右移一位。需要注意的是,在 Python 中,整数默认是有符号的,但这里题目输入是无符号整数,在实际应用场景中,如果输入确实是无符号整数,要确保输入范围在合理的无符号整数范围内,避免潜在的符号问题。
3. 解题思路(转二进制)
除了使用位运算直接操作二进制位,我们还可以通过将整数转换为二进制字符串,然后统计字符串中 1 的个数来解决这个问题。以下是 C# 语言的实现代码:
3.1 C#
public class Solution
{
public int HammingWeight(uint n)
{
var count = 0;
while (n != 0)
{
if (n % 2 == 1)
count++;
n /= 2;
}
return count;
}
}
在这段 C# 代码中,在Solution
类中定义了HammingWeight
方法,接收一个无符号整数n
。通过while
循环,只要n
不为 0 就继续循环。在循环内部,通过n % 2 == 1
判断n
的当前最低位是否为 1,如果是则将count
加 1,然后通过n /= 2
将n
除以 2,相当于将二进制数右移一位,继续检查下一位。这种方法虽然思路直观,但相较于位运算,在效率上可能会稍逊一筹,因为转换为二进制字符串以及逐字符统计的操作相对复杂一些。
通过对 LeetCode 191 题的深入分析和不同解法的探讨,我们不仅掌握了如何解决计算二进制中 1 的个数这类问题,还了解了位运算在实际编程中的强大应用以及不同编程语言在处理这类问题时的特点和实现方式。希望这些知识和思路能为大家在算法学习和编程实践中提供有益的帮助。