题目链接
https://leetcode.cn/problems/1nzheng-shu-zhong-1chu-xian-de-ci-shu-lcof/
思路
三种情况,都可以由cur=0演化而来。
1)当cur=0时,以23045为例子,求百位位置上出现1的次数。此时可选范围是00100—22199,high有23种排列组合,low有100种排列组合,所以百位位置上出现1的次数总数为:23x100–>即highxdigit;
2)当cur=1时,以23145为例子,求百位上出现1的次数。此时可以把0-23145拆分成两项:0-23045以及23046-23145。那么0-23045可以由第一种情况得出结果:highxdigit=23x100。剩下的工作就是求23046-23145中百位出现1的次数,显然只有23100~23145才满足要求,所以第二项的结果就是low+1=45+1。总的公式为highxdigit+low+1;
3)当cur>1时,以23345为例子,求百位上出现1的次数,此时可以把0-23345拆分成0-23199以及23200-23345。第二项23200-23345显然没有满足要求的数字。那么求0-23199中百位出现1次数可以由第二种情况得出:highxdigit+low+1=23x100+99+1。由于cur是>1的,所以所求的数字(23345)向下取到 满足要求的最大数字(23199)时,low位数字必然是99,而0~99个数正好是digit(100=99+1)。所以可以把22345转化为22199,此时公式为highxdigit+low+1 = highxdigit+digit=(high+1)xdigit。
由此看出,cur=1可以由cur=0演变过来,cur>1可以由cur=1演变过来
注意跳出循环条件,这里cur!=0是为了解决输入个位数字(1-9)的问题
代码
class Solution {
public int countDigitOne(int n) {
int low=0,cur=n%10,high=n/10,digit=1;
int sum=0;
while (high!=0 || cur!=0){
if(cur==0) sum+=high*digit;
else if(cur==1) sum+=high*digit+low+1;
else sum+=(high+1)*digit;
low+=cur*digit;
cur=high%10;
high/=10;
digit*=10;
}
return sum;
}
}