原题如下:
笔者思路比较正常,是模拟正常加1情况下的数字变化,规律如下:
1、当上一个字符中有0时,下一次运算会将最右位置的0置1,将这个0的位置x后的1全部改为0;
这个字符中1的个数为为n+1-(len(s)-1-x),其中n表示上个字符中1的个数,+1表示将最右边的0置1,(len(s)-1)-x代表原来0后边的1的个数,置为0以后减去即可。
2、当上一个字符没有0时,所有1变0,同时开头补1。
此时n的个数为1。
class Solution:
def countBits(self, num: int) -> List[int]:
s="0"
n=0
lst=[0]
for index in range(1,num+1):
if s.find("0")+1:
x=s.rfind("0")
s=s[:x]+"1"+"0"*(len(s)-1-x)
n+=x+2-len(s)
else:
s="1"+"0"*len(s)
n=1
#print(s,n)
lst.append(n)
return lst
大佬思路(动态规划),原文链接:
0中1的个数为0,对于此后的数字,:
(1)若为奇数,则相比于上一个偶数只是最后一位从0到1,n+=1即可,此时dp[n]=dp[n-1]+1。
(2)若为偶数,则其二进制相比于n/2只是左移一位,右边补0,即其中1的个数相等,dp[n]=dp[n//2]
笔者代码如下(其中判断奇偶采用了位运算x&1,奇数得1,偶数得0,比对2取余要快):
class Solution:
def countBits(self, num: int) -> List[int]:
dp=[0]
for index in range(1,num+1):
if index&1:
dp.append(dp[-1]+1)
else:
dp.append(dp[index//2])
return dp