从1到整数n中1出现的次数
题目:输入一个整数n,求从1到n这n个整数的十进制表示中1出现的次数。例如输入12,从1到12这些整数中包含1的数字有1,10,11和12共出现了5次。
不考虑时间效率的解法:
1 int NumberOf1Between1AndN(unsigned int n) 2 { 3 int number=0; 4 for(unsigned int i=1;i<=n;++i) 5 number +=NumberOf1(i); 6 return number; 7 } 8 int NumberOf1(unsigned int n) 9 { 10 int number=0; 11 while(n) 12 { 13 if(n%10==1) 14 number++; 15 n=n/10; 16 } 17 return number; 18 }
从数字规律着手明显提高时间效率:
1 int Numberof1Between1AndN(int n) 2 { 3 if(n<=0) 4 return 0; 5 char strN[50]; 6 sprintf(strN,"%d",n);//将整数转换为字符串 7 return NumberOf1(strN); 8 } 9 10 int NumberOf1(const char* strN) 11 { 12 if(!strN||*strN<'0'||*strN>'9'||*strN=='\0') 13 return 0; 14 int first=*strN-'0'; 15 unsigned int length=static_cast<unsigned int>(strlen(strN)); 16 if(length==1&&first==0) 17 return 0; 18 if(length==1&&first>0) 19 return 1; 20 21 int numFirstDigit=0; 22 if(first>1) 23 numberFirstDigit=PowerBase10(length-1); 24 else if(first==1) 25 numFirstDigit=atoi(strN+1)+1;//将字符串转换为整数 26 27 int numOtherDigits=first*(length-1)*PowerBase10(length-2); 28 int numRecursive=NumberOf1(strN+1); 29 30 return numFirstDigit+numOtherDigits+numRecursive; 31 } 32 33 int PowerBase10(unsigned int n) 34 { 35 int result=1; 36 for(unsigned int i=0;i<n;++i) 37 result *=10; 38 return result; 39 } 40