微软100题(30)1到n中1出现的次数

来源:互联网 发布:2015网络十大洗脑神曲 编辑:程序博客网 时间:2024/05/18 01:31

题目:输入一个整数n,求从1到n这n个整数的十进制表示中1出现的次数。

例如输入12,从1到12这些整数中包含1 的数字有1,10,11和12,1一共出现了5次。

 

暴力法:

int NumberOf1Between1AndN(int n){int number = 0;for (int i=1;i<=n;i++)   number += NumberOf1(i);return number;}int NumberOf1(int n){int cnt=0;while (n){if(n % 10 == 1)cnt++;n = n/10;}return cnt;}

更聪明的方法,参考《剑指offer》

int NumBerOf1Between1AndN(int n){if(n<0) return 0;char str[100];sprintf(str,"%d",n);return NumberOf1Recursively(str);}int NumberOf1Recursively(char* str){if(!str || *str = '\0'||*str<'0'||*str>'9')return 0;int first = *str-'0';unsigned length = static_cast<unsigned int>(strlen(str));if(length==1 && first==0) return 0;if(length==1 && first>0) return 1;//计算最高位为1的个数int firstDigit = 0;if(first>1)firstDigit = PowerBase10(length-1);else if(first==1)firstDigit = atoi(str+1)+1;//计算中间位有1,以23456为例,firstDigit = 10000,代表10000——19999,这些数//3456——23456除万位为1的,另外4为,随意一位为1,其它为0-9随意,分成3456——13455和13456——23456两端//每段都有C(4,1)*10*10*10int MiddleDigit = first*(length-1)*PowerBase10(length-2);//递归计算1-3456int RecurDigit = NumberOf1Recursively(str+1);return firstDigit+MiddleDigit+RecurDigit;}int PowerBase10(int n){int result=1;for (int i=1;i<=n;++i){result = result*10;}return result;}



 


 

0 0
原创粉丝点击