int Count(unsigned int v) { int num = 0; while(v) { v &= (v-1); num++; } return num; }
这种方法速度比较快,其运算次数与输入n的大小无关,只与n中1的个数有关。如果n的二进制表示中有k个1,那么这个方法只需要循环k次即可。
其原理是不断清除n的二进制表示中最右边的1,同时计数器加1,直至n为0。
对于int 型32位的呢
def NumberOf1( n): min_val=-2**31 if n ==min_val: return 1 if n>=0: num=0 else: num=1 while n!=0 and n>min_val: n&=n-1 num+=1 return num
int型32位表示范围为-2^31~2^31-1,最高位表示符号位,负数比正数多一位,多的这以为就是100000000000000,就是-0,也就是-2^31。
在判断1的个数的时候,负数的符号位也为1,所以也要加入判断,所以如果n为负数,则初始化的时候,num=1
计算十进制数中1的个数
给定一个数n,计算从1~n中所有数字中出现1的次数总和。
f(13)=6
f(23)=13
f(24)=14
通过分析发现:f(n)=个位出现1的次数+十位出现1的次数+百位出现1的次数+...
某一位出现1的个数总结,以十位为例:
如果十位是0:以1101为列,十位出现1的个数10~19,110~119,210~219,...,910~919,1010~1019共计110个,说白了就是在十位出现1(10~19)的情况下,最高的两位可以不停的变化,从00~10,共00,01,02,..,10,共计11种情况,每种情况下都对应低位的(10~19)10个,所以共计110个出现1。总结为highNum*factor(如果是计算十位个数,factor=10,百位factor=100)
如果十位是1:同上分析,则为highNum*factor+lowerNum+1,多了一个低位数加1,就是既与高位数有关,也与低位数有关。
如果十位大于1:则为(highNum+1)*factor。
def sum1s(n): count=0 factor=1 while n//factor: lowerNum=n%factor currNum=(n//factor)%10 highNum=n//(factor*10) if currNum==0: count+=highNum*factor elif currNum==1: count+=highNum*factor+lowerNum+1 else: count+=(highNum+1)*factor factor*=10 return count
这样的话计算一个1~n数中,所有出现1的个数时间复杂度为O(log10(n)),也就是只与n的位数有关系了。