难度:中等
题目
输入一个整数 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
解答
思路
分成两部分计算
计算 1 到 99..9 (n-1个9) 有几个 1
计算 从 10..0(n-1个0) 到 a1a2...an 有几个1
前者可以通过找规律,计算出值。
后者也是通过找规律,但是需要考虑一些特殊情况,比如改为是0或者1,则与其他数字不同。
知识点
代码
class Solution {
public:
int countDigitOne(int n) {
if(n==0) return 0;
int size = (int)(log10(n))+1;
return cal_1_n_1x0_To_n(n,size)+cal_1_To_n_1x9(size-1);
}
int cal_1_n_1x0_To_n(int n,int size)
{
int saveN=n;
int allOne=0;
if(n/(int)pow(10,size-1)==1)
{
allOne+=n-pow(10,size-1)+1;
}
else
{
allOne+=pow(10,size-1);
}
char temp;
for(int i=1;i<size;i++)
{
temp=n%10;
n=n/10;
if(temp==0)
{
allOne+=(int)(n-pow(10,size-i-1))*pow(10,i-1);
}
else if(temp==1)
{
allOne+=(int)(n-pow(10,size-i-1))*pow(10,i-1)+saveN%(int)(pow(10,i-1))+1;
}
else
{
allOne+=(int)(n-pow(10,size-i-1)+1)*pow(10,i-1);
}
}
return allOne;
}
int cal_1_To_n_1x9(int digit)
{
if(digit==0)
{
return 0;
}
int a=1,b=0;
a=1;
for(int i=1;i<digit;i++)
{
b=pow(10,i)+(9*pow(10,i-1))*i+a;
a=b;
}
return a;
}
};