Leetcode: 比特位计数

38 阅读2分钟

原题: leetcode.cn/problems/co…

题目描述

给定一个非负整数 n,计算从 0n 的每个数字的二进制表示中 1 的个数,并以数组形式返回。要求:

  • 算法时间复杂度为 O(n)O(n)
  • 空间复杂度为 O(n)O(n)

解题思路

核心思想:利用动态规划高效计算二进制中1的个数,通过已计算的结果推导新值。

  1. 动态规划方法

    • 状态定义dp[i] 表示数字 i 的二进制中 1 的数量
    • 转移方程
      • dp[i] = dp[i >> 1] + (i & 1)
      • 解释:数字 i 的 1 的数量 = i/2 的 1 的数量 + i 的最低位是否为 1
    • 初始化dp = 0
  2. 关键特性

    • 奇偶规律
      • 偶数:dp[i] = dp[i/2](最低位为0)
      • 奇数:dp[i] = dp[i/2] + 1(最低位为1)
    • 位运算优化:使用 i >> 1 代替除法,i & 1 代替取模

复杂度分析

指标说明
时间复杂度O(n)O(n)只需遍历一次数组
空间复杂度O(n)O(n)存储结果数组

代码实现

  • JavaScript
var countBits = function(n) {
    const dp = new Array(n + 1).fill(0);
    for (let i = 1; i <= n; i++) {
        dp[i] = dp[i >> 1] + (i & 1);
    }
    return dp;
};
  • python
def countBits(n: int) -> list[int]:
    dp = [0] * (n + 1)
    for i in range(1, n + 1):
        dp[i] = dp[i >> 1] + (i & 1)
    return dp
  • rust
impl Solution {
    pub fn count_bits(n: i32) -> Vec {
        let n = n as usize;
        let mut dp = vec![0; n + 1];
        for i in 1..=n {
            dp[i] = dp[i >> 1] + (i & 1) as i32;
        }
        dp
    }
}

实际应用场景

  1. 加密算法:快速计算汉明权重(如SHA-256)
  2. 图像处理:二进制图像的特征提取
  3. 数据压缩:评估二进制数据的熵值
  4. 遗传算法:计算DNA序列的相似度
  5. 错误检测:CRC校验中的位计算

相似题目

  1. 汉明距离
    • 解题思路:x ^ y 后计算二进制中1的数量
    • 关联点:相同位计数技术
  2. 数字的补数
    • 解题思路:取反位并清除前导零
    • 关联点:位操作基础
  3. 二进制表示中质数个1
    • 解题思路:组合位计数与质数判断
    • 进阶应用:位计数结果的二次处理