📅  最后修改于: 2023-12-03 15:27:59.038000             🧑  作者: Mango
这个主题主要是关于计算从1到N的所有数字中的总设置位的问题。对于程序员来说,这涉及到数学和编程的知识。
假设我们要计算从1到N的所有数字中的总设置位,其中一个数字的设置位数是指该数字中1的个数。例如,数值10的二进制表示是1010,因此它具有2个设置位。
我们可以通过以下几种方法解决这个问题。其中,前两种方法是暴力枚举,第三种方法是一种优化算法。
这个方法是最直接的方法,我们可以从1到N枚举每个数字,并计算它们中1的个数。最后将它们加起来就能得到总数。
def countSetBits1(n: int) -> int:
def countSetBits(x: int) -> int:
cnt = 0
while x:
if x & 1:
cnt += 1
x >>= 1
return cnt
res = 0
for i in range(1, n + 1):
res += countSetBits(i)
return res
这种方法与第一种方法相似,只是对于每个数字,它们的1的个数不是一个一个数的统计,而是一位一位地统计。
def countSetBits2(n: int) -> int:
res = 0
for i in range(32):
for j in range(1, n + 1):
res += (j >> i) & 1
return res
这种方法则是一种更为优化的方法,它可以将时间复杂度降到O(logN)。
在二进制形式中,一个数字除了最高位,其它各位上都可以转化为比它低一位的数字上1的个数,例如:
因此,我们可以通过这个关系推导出一个动态规划方程,可以在O(logN)的时间复杂度内求解。
def countSetBits3(n: int) -> int:
dp = [0] * 33
for i in range(1, 33):
dp[i] = dp[i - 1] * 2 + (1 << (i - 1))
res = 0
for i in range(32, -1, -1):
if n >= (1 << i):
res += dp[i] + (n - (1 << i) + 1) + countSetBits3(n - (1 << i))
return res
综上所述,我们可以通过不同的方法计算从1到N的所有数字中的总设置位,其中最优解决方案是动态规划。但是,我们也应该注意到,这种问题的解决方法并不限于这些,通过增加别的方法也是完全可行的。
如果你对此有所收获,请给个Star支持一下哦:https://github.com/youngyangyang04/leetcode-master。