1~n整数中1出现的次数
输入一个整数 n ,求1~n这n个整数的十进制表示中1出现的次数。
例如,输入12,1~12这些整数中包含1 的数字有1、10、11和12,1一共出现了5次。
示例 1:
输入:n = 12
输出:5
示例 2:
输入:n = 13
输出:6
限制:
- 1 <= n < 2^31
解法一(除10取余法),超时
class Solution {
public:
int countDigitOne(int n) {
if(n <= 0)
return 0;
int result = 0;
for (int i = 1; i <= n; ++i) {
result += oneInNumber(i);
}
return result;
}
int oneInNumber(int num){
int count = 0;
while(num > 0){
if(num%10 == 1)
count++;
num = num/10;
}
return count;
}
};
解法二(通过数字的规律提高时间效率)
class Solution {
public:
int countDigitOne(int n) {
if(n <= 0)
return 0;
char str[50];
sprintf(str,"%d",n); // itoa无法使用
return NumberOf1(str);
}
int NumberOf1(const char* str){
if(*str<'0' || *str>'9' || *str=='\0')
return 0;
int first = *str - '0';
int length = strlen(str); //字符串及字符数组长度函数的使用
if(length == 1 && first == 0)
return 0;
if(length == 1 && first > 1)
return 1;
int numFirstDigit = 0;
// 计算21345中,10000~19999中第一位为1时的个数
if(first > 1)
numFirstDigit = pow(10,length - 1);
else if(first == 1)
numFirstDigit = atoi(str+1) + 1;
// 计算五位数时,第一位固定时,后面四位依次为1时的个数
int numOtherDigit = first * (length-1) * pow(10,length-2);
// 递归计算。将最高位去掉,计算四位数时,即1~1345中的数目
int numRecursive = NumberOf1(str + 1);
return numFirstDigit + numOtherDigit + numRecursive;
}
};