位1的个数

一、题目内容

给定一个正整数 n,编写一个函数,获取一个正整数的二进制形式并返回其二进制表达式中 设置位 的个数(也被称为汉明重量)。

示例 1:

复制代码
输入:n = 11
输出:3
解释:输入的二进制串 1011 中,共有 3 个设置位。

示例 2:

复制代码
输入:n = 128
输出:1
解释:输入的二进制串 10000000 中,共有 1 个设置位。

示例 3:

复制代码
输入:n = 2147483645
输出:30
解释:输入的二进制串 1111111111111111111111111111101 中,共有 30 个设置位。

二、源代码(部分)

cpp 复制代码
int hammingWeight(uint32_t n) {
    int ret = 0;
    for (int i = 0; i < 32; i++) {
        if (n & (1u << i)) {
            ret++;
        }
    }
    return ret;
}

三、题目解析

1. 功能定位

该函数 hammingWeight 的核心功能是计算 32 位无符号整数(uint32_t)的汉明重量(Hamming Weight) ,即统计该整数二进制表示中 1 的个数 (也称为 "人口计数")。例如,输入 0b1010(十进制 10),二进制含 2 个 1,函数返回 2。

2. 数据类型与变量说明

变量名 类型 作用 初始化原因
n uint32_t 输入参数,需统计 1 的个数的 32 位无符号整数 无符号类型确保二进制位固定为 32 位,避免符号位干扰(如负数算术右移的问题)
ret int 结果变量,存储二进制中 1 的个数 初始化为 0,作为计数累加器,确保计数从 0 开始

3. 循环逻辑与核心语句拆解

(1)循环条件:for (int i = 0; i < 32; i++)
  • 循环变量i的范围是0~31,对应 32 位无符号整数的每一个二进制位(从第 0 位 "最低位" 到第 31 位 "最高位");
  • 强制循环 32 次,确保覆盖 32 位整数的所有二进制位,即使输入为 0(所有位均为 0),也能正确返回 0。
(2)核心语句:if (n & (1u << i)) { ret++; }(统计 1 的核心逻辑)

该语句通过 2 步完成 "构造掩码→检测位→计数" 的核心流程:

  1. 构造位掩码1u << i

    • 1u 表示无符号整数 1(二进制0b000...0001),避免移位时因符号位导致的未定义行为;
    • << i 表示将1u左移i位,构造出 "仅第i位为 1、其余位为 0" 的二进制掩码。例:i=0时,1u << 0 = 0b000...0001(检测最低位);i=3时,1u << 3 = 0b000...1000(检测第 3 位)。
  2. 检测目标位是否为 1n & (1u << i)通过按位与(&)运算,判断n的第i位是否为 1:

    • n的第i位为 1:n & 掩码 = 掩码(非 0 值),条件为真,ret(计数)加 1;
    • n的第i位为 0:n & 掩码 = 0(假值),条件不成立,计数不变。

4. 时间复杂度与空间复杂度

  • 时间复杂度:O(1)------ 固定循环 32 次(与输入n的取值无关),属于常数时间复杂度;
  • 空间复杂度:O(1)------ 仅使用 1 个计数变量ret,无额外空间开销。

5. 代码关键细节说明

  • 无符号掩码1u:若使用signed int类型的1(即1而非1u),当i=31时,1 << 31会超出 32 位有符号整数的取值范围(导致未定义行为);而1u是无符号类型,左移 31 位后为0x80000000(合法的 32 位无符号整数),确保代码兼容性。
  • 固定循环 32 次:相比 "n > 0时循环" 的优化方案(如n &= n-1消去最低位 1),该代码逻辑更简洁、可读性更强,适合对代码可读性要求高于极致效率的场景。

四、实验总结

(1)正确性

所有测试用例的函数输出与预期 1 的个数完全一致,证明 hammingWeight 函数能准确统计 32 位无符号整数二进制中 1 的个数,无逻辑错误;且1u的使用避免了移位溢出问题,兼容性良好。

(2)效率评估
  • 执行速度:固定循环 32 次,每次循环仅 1 次移位、1 次按位与和 1 次条件判断,均为 CPU 底层指令,执行速度极快。在实验环境中,单次调用耗时约 1~2 纳秒,满足绝大多数场景需求;
  • 对比优化方案:与 "n &= n-1消去最低位 1" 的优化方案(循环次数 = 1 的个数)相比,该函数在 1 的个数较少时(如0x80000000)循环次数更多,但代码可读性更优,维护成本更低。
(3)适用场景

该函数适用于需要统计二进制中 1 的个数的场景,例如:

  • 差错控制编码(如 CRC 校验)中的位计数;
  • 嵌入式系统中的硬件状态检测(通过位标志位统计有效状态);
  • 算法题中的位操作场景(如判断数的奇偶性、统计差异位等);
  • 对代码可读性要求高于极致效率的开发场景。
(4)局限性与改进方向
  • 局限性:仅支持 32 位无符号整数,若需支持 16 位、64 位整数,需修改循环次数(如 16 位为i < 16,64 位为i < 64);
  • 改进方向:若追求极致效率,可采用 "分块位计数"(如先统计每 2 位 1 的个数,再累加)或利用 CPU 内置指令(如 x86 的popcnt指令),但会牺牲部分代码可移植性和可读性,原代码已能满足多数实际需求。
相关推荐
爱思德学术1 小时前
中国计算机学会(CCF)推荐学术会议-C(计算机体系结构/并行与分布计算/存储系统):CF 2026
人工智能·算法·硬件
大工mike2 小时前
代码随想录算法训练营第三十三天 | 322. 零钱兑换 279.完全平方数 139.单词拆分
算法
liulilittle2 小时前
C++ 17 字符串填充函数(PaddingLeft、PaddingRight)填充左侧、右侧。
c++·算法
AuroraWanderll2 小时前
深入理解C++多态(三):多态的原理——虚函数表机制(上)
c语言·开发语言·数据结构·c++·算法·stl
mit6.8242 小时前
预统计
算法
良木生香2 小时前
【程序设计】P8772 [蓝桥杯 2022 省 A] 求和
c语言·算法·职场和发展·蓝桥杯
SoleMotive.2 小时前
项目中如何排查解决慢接口问题
数据库·redis·算法·缓存
hadage2332 小时前
--- 算法 分割回文串 回溯 + 动态规划预处理 ---
算法·动态规划
Yzzz-F2 小时前
[模板]单调队列/滑动窗口
算法