📅  最后修改于: 2023-12-03 15:27:58.981000             🧑  作者: Mango
在计算机科学中,“置位”是指二进制数字中为1的位数。在此题目中,要求计算从1到n的所有数字中的总置位位数。例如,若n=5,则从1到5的所有数字中,二进制表示中的置位一共有7个。
求从1到n的所有数字中的置位位数,显然需要遍历1到n的所有数字。同时,需要对每个数字进行二进制位逐一检查,以计算置位数。我们可以使用以下两种方法:
我们既可以将每个数字转换为二进制字符串,然后统计其中的“1”的个数;也可以使用位运算,逐位取出二进制位并检查其是否为1。这是一种非常naive的方法,时间复杂度为O(nlogn)。
def count_set_bits_naive(n: int) -> int:
count = 0
for i in range(1, n+1):
count += bin(i).count('1')
return count
方法1中的代码看起来非常简洁,但效率比较低。我们可以采用一些技术来优化时间复杂度。一个常用的技术是快速幂(见此)。实际上,快速幂可以用于快速计算二进制下的1的个数。
我们可以定义一个递归函数count_set_bits_fast_util()
,该函数传递两个参数:n和p。其中n是当前需要计算置位位数的数字,p是当前数字所在的2的次幂。例如,当n=50时,p=32,因为50落在32和64之间。
函数count_set_bits_fast_util()
的返回值是当前数字n的置位位数。
def count_set_bits_fast_util(n: int, p: int) -> int:
if n == 0:
return 0
elif n < p:
return count_set_bits_fast_util(n, p//2)
else:
return n//p * p//2 + (n%p + 1) + count_set_bits_fast_util(n%p, p//2)
def count_set_bits_fast(n: int) -> int:
p = 1
while p <= n:
p *= 2
p //= 2
return count_set_bits_fast_util(n, p)
为了验证两种方法的正确性,我们可以编写以下测试:
def test_count_set_bits():
n = 50
assert count_set_bits_naive(n) == count_set_bits_fast(n) == 78
n = 100
assert count_set_bits_naive(n) == count_set_bits_fast(n) == 312
n = 1000
assert count_set_bits_naive(n) == count_set_bits_fast(n) == 4992
n = 1000000
assert count_set_bits_naive(n) == count_set_bits_fast(n) == 4888952
test_count_set_bits()
测试结果表明,两种方法得出的置位位数都是正确的。
本题要求计算从1到n的所有数字中的总置位位数。我们可以使用naive方法(每个数字转换为二进制后统计“1”的个数)或快速方法(使用快速幂)来完成此任务。快速方法的时间复杂度为O(logn)。