统计1到N的所有数中1出现的次数,只需要计算1出现在每一位上的次数
分析:N有n位,将n位数记作(x1)...(xi-1)(xi)(xi+1)...(xn), 前i-1位组成的数记作X前, 后n-i位组成的数记作X后。
一般地,求第i位为1时的数字个数,分三种情况
- N的第i位为0:X前要小于(x1)...(xi-1),X后随意,共((x1)...(xi-1) )*10的n-i次方个
- N的第i位为1: 两种情况A. X前小于(x1)...(xi-1),X后随意,同上; B. X前为(x1)...(xi-1), X 后小于等于(xi+1)...(xn),共(xi+1)...(xn) + 1个
- N的第i位大于1: X前(x1)...(xi-1)内取值, X后随意
class Solution {
public:
int decimalLen(int N)
{
int len = 1;
while ((N /= 10) != 0)
{
len++;
}
return len;
}
void split(int N, int len, int loc, int &x, int &k, int &y)
{
int tmp = pow(10, len - loc);
x = N / (tmp * 10);
y = N % pow(10, len - loc);
k = (N / tmp) % 10;
}
int pow(int a, int b)
{
int ret = 1;
for (int i = 0; i < b; i++)
{
ret *= a;
}
return ret;
}
int NumberOf1Between1AndN_Solution(int N)
{
int n = decimalLen(N);
int sum = 0;
for (int i = 1; i <= n; i++)
{
int x = 0;
int k = 0;
int y = 0;
split(N, n, i, x, k, y); //将n位数N以i位为准,拆分成x,k和y三分部,其中k是第i位
if (k == 0)
{
sum += x * pow(10, n - i);
}
else if (k == 1)
{
sum += x * pow(10, n - i) + (y + 1);
}
else
{
sum += (x + 1) * pow(10, n - i);
}
}
return sum;
}
};