《编程之美》第2.4节:1的数目
题目:给定一个十进制整数N,写下从1开始,到N的所有整数,然后数一下其中出现的所有"1"的个数。
方法一:暴力枚举,肯定能够算出来,但是这样的复杂度为O(NlgN)。
方法二:寻找规律,用公式计算,复杂度为O(lgN)。当某一位的数为0时,这个位上出现1的总次数就等于其高位数字乘以其所在位的权重,加入21023,百位为0,则其出现1的个数为21*100,100是0所在位的权重。如果为1,则等于其高位数字乘以其所在位置的权重,然后加上其低位数字再加1,如21123,出现1的个数为21*100+23+1,+1的原因是由于100这个特殊的情况。如果当前位不为0也不为1,则等于其高位数字+1在乘以其所在位置的权重,如21223,出现1的个数(21+1)*100,其中+1的原因是:当前位已经大于1了,因此相当于1已经出现了。
#include<iostream>
using namespace std;
unsigned long count1InAnInteger1(unsigned long n)
{
unsigned long result=0;
for(int i=1;i<=n;i++)
{
unsigned long temp=i;
while(temp)
{
if(temp%10==1)
result++;
temp/=10;
}
}
return result;
}
unsigned long count1InAnInteger2(unsigned long n)
{
unsigned long result=0;
unsigned long high=0,low=0,temp=n,bit=0,pow10=1;
int curr=0;
while(pow10<=temp)
{
low=temp%pow10;
high=temp/pow10/10;
curr=high%10;
switch(curr)
{
case 0:
result+=high*pow10;
break;
case 1:
result+=high*pow10+low+1;
break;
default:
result+=(high+1)*pow10;
break;
}
pow10*=10;
}
return result;
}
int main()
{
cout<<count1InAnInteger1(10000)<<endl;
cout<<count1InAnInteger2(10000)<<endl;
system("pause");
return 0;
}