小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
题目
输入一个整数 n ,求1~n这n个整数的十进制表示中1出现的次数。
例如,输入12,1~12这些整数中包含1 的数字有1、10、11和12,1一共出现了5次。
难度:hard
思路
1.首先1~n这n个整数的1出现的个数可以看成每个位上1出现个数的和例如个位上面1出现的个数+十位上面1出现的个数+百位上1出现的个数...
2.将每个位上面的数分成3中情况
以数字21034为例,cur表示当前所在位置上面的数,left表示cur左边部分的数,right表示cur右边部分的数,
①cur大于1的情况
由于十位上面的数为3大于1,那么十位上面的为1可以组成的数字为:
left部分可以取到的数为 0 ~ 210,right部分可以取到的数为 0 ~ 10
那么就是:(left+1)*10个数
②cur小于1的情况(就是cur==0)
由于百位上面的数为0小于1,那么百位上面为1可以组成的数字为:
left部分可以取到的数为0 ~ 20(因为如果百位取到1的话那么211??就大于原来的数,所以取不到21)
right部分可以取到的数为 0 ~ 100
那么就是: left * 100 个数
③cur 等于 1的情况
那么千位上面为1可以组成的数字为:
left部分可以取到的数为 0 ~ 2,当left!=2的时候right可以取到0 ~ 100,当left == 2的时候right只能取到0~right(这是因为21035比n大)
那么就是:( left * 1000 + right + 1) 个数
注意下结束条件为: left != 0 || cur != 0
代码
class Solution {
public int countDigitOne(int n) {
int left = n / 10;
int cur = n % 10;
int right = 0;
int res = 0;
int base = 1;
while (cur != 0 || left != 0) {
if (cur > 1) {
res += (left + 1) * base;
} else if (cur < 1) {
res += left * base;
} else if (cur == 1) {
res += left * base + right + 1;
}
right += cur * base;
cur = left % 10;
left = left / 10;
base *= 10;
}
return res;
}
}