编写一个函数,输入是一个无符号整数(以二进制串的形式),返回其二进制表达式中数字位数为 ‘1’ 的个数(也被称为汉明重量)。
#include <iostream>
#include <cstdint>int hammingWeight(uint32_t n) {if (n > 0 && n <= UINT32_MAX) {int count = 0;while (n != 0) {count++;n = n & (n - 1);}return count;} else {std::cerr << "Input value out of range. Please provide a value between 0 and " << UINT32_MAX << std::endl;return -1; // 返回一个错误代码或者其他适当的值表示输入有误}
}int main() {uint32_t num = 23; // 00000000000000000000000000010111 in binaryint weight = hammingWeight(num);if (weight != -1) {std::cout << "Number of '1' bits: " << weight << std::endl;}return 0;
}
使用一种称为 Brian Kernighan’s Algorithm 的经典技巧来计算一个数字中二进制位为1的个数,它的运行时间与该数字中二进制位为1的个数成正比。下面是这段代码的执行过程:
初始化计数变量 count 为 0。
当输入的无符号整数 n 不为 0 时,执行循环。
在循环中,每次执行 n = n & (n - 1) 操作,这将把 n 中最右边的 1 变为 0。
同时,count 加 1,表示发现了一个二进制位为 1 的位置。
当 n 变为 0 时,说明所有的二进制位都被遍历完毕,此时返回 count,即为二进制表达式中数字位数为 ‘1’ 的个数。
这种算法的关键在于每次执行 n = n & (n - 1) 操作,都会消去 n 中最右边的 1,因此循环的次数最多等于 n 的二进制位为 1 的个数。这使得这个算法的时间复杂度与二进制位为 1 的个数成正比,而不是与 n 的位数成正比,因此效率非常高。
时间复杂度:该算法的时间复杂度取决于输入的数字 n 中二进制位为 1 的个数。在最坏情况下,时间复杂度为 O(log n),其中 n 是输入的数字。由于这个算法只会遍历二进制表示中为 1 的位数,因此时间复杂度与输入中二进制位为 1 的个数成正比。
空间复杂度:该算法并不需要额外的空间来存储中间结果,只需要一个常数级别的额外空间用于存储计数器和循环变量。因此,空间复杂度为 O(1),即常数级别的空间复杂度。