问题:给定一个十进制整数N,求出从1到N的所有整数中出现”1”的个数。
解法一:
最直接的方法就是从1开始遍历到N,将其中每一个数中含有“1”的个数加起来,就得到了问题的解。
1 int CountOne(int N){ 2 int num=0; 3 while(N){ 4 num+=((N%10==1)?1:0); 5 N/=10; 6 } 7 return num; 8 }
此方法简单,容易理解,但它的问题是效率,时间复杂度为O(N * lgN),N比较大的时候,需要耗费很长的时间。
解法二:
归纳法寻找N的各位中包含1的规律:
如果当前位上的数字为0,则在该位上出现1的次数由更高位决定,等于更高位乘以当前位数(十位为10,百位为100);
如果当前位上的数字为等于1,则该位上出现1的次数由高位和低位共同决定:等于高位乘以当前位数加上低位数字加1;
如果当前位上的数字大于1,则该位上出现1的次数由高位决定:等于高位数字加1然后乘以当前的位数。
int CountOne1(int N){ int num=0; while(N){ num+=((N%10==1)?1:0); N/=10; } return num; } int CountOne(int N){ int iLow; int iCurr; int iHigh; int iCount; int iFactor=1; while(N/iFactor){ iLow=N-(N/iFactor)*iFactor; iCurr=N/iFactor%10; iHigh=N/(iFactor*10); switch(iCurr){ case 0: iCount+=iHigh*iFactor; break; case 1: iCount+=iHigh*iFactor+iLow+1; break; default: iCount+=(iHigh+1)*iFactor; break; } iFactor*=10; } return iCount; } int main(){ int N,sum=0; cin>>N; clock_t start,end; start=clock(); /* for(int i=1;i<=N;++i){ sum+=CountOne1(i); } cout<<sum<<endl; */ cout<<CountOne(N)<<endl; end=clock(); cout<<(double)(end-start)/CLOCKS_PER_SEC<<endl; system("pause"); return 0; }