LeetCode-面试题 17.06. 2出现的次数
题目描述
编写一个方法,计算从 0 到 n (含 n) 中数字 2 出现的次数。
示例
输入: 25
输出: 9
解释: (2, 12, 20, 21, 22, 23, 24, 25)(注意 22 应该算作两次)
题解
一看到这道题,可能很多人的想法和我一样,去遍历 0 到 n中的每一个数,依次计算2出现的次数。
public int numberOf2sInRange(int n) {
int count=0;
for(int i=1;i<=n;i++){
int tmp=i;
while (tmp>0){
if (tmp%10==2){
count++;
}
tmp/=10;
}
}
return count;
}
但是这样的复杂度太高,遇到比较大的数就过不去了。下面来介绍一种更加快捷的方法。
由低到高依次来计算每一位上2出现的次数。那么如何来确定每一位上2的个数呢?
先定义四个变量factor,low,cur,high分别表示所在位(个位,十位),低位的值,当前位的值和高位的值,
根据cur的值的情况来计算当前位上2所出现的次数。
cur的值可以分为三种情况:小于2;等于2;大于2,下面以321为例对三种情况进行说明。
1.小于2
此时cur在个位,它的高位是32,低位为0,factor=1,在这种情况下个位出现2的次数又是多少呢?
count=high*factor;因为个位小于2,所以不可能出现322
所以个位出现2的情况有(0-31)2(即02,12,22,32…302,312)总共high*factor次;
2.等于2
此时cur在十位,它的高位是3,低位为1,factor=10,在这种情况下十位出现2的次数又是多少呢?
count=(highfactor)+low+1;count由两部分组成highfactor和low+1;
十位上出现2,可能会有(20~29)10个十位上存在2的数,那么可能存在几组这样的数呢?high组。
即(0(20-29),1(20-29),2(20-29))=(high*factor)。
但十位上出现2的次数还没有算完,(high*factor)计算完了当前高位之前的十位上2出现的所有数,以当前高位为起点十位上还会出现2,有多少个呢?low+1即(320,321).
所以cur=2时,该位上2出现的次数为(high*factor)+low+1次。
3.大于2
此时cur在百位,它的高位是0,低位为2,factor=100。cur大于2,那该位上肯定可以出现2。
百位上出现2,可能会有(200-299)100个百位上存在2的数,那么可能存在几组这样的数呢?(high+1)组。
以当前为例即百位数出现2的次数总共有(200-299)共100个。
所以cur大于2时,该位上2出现的次数为(high+1)*factor次。
具体代码如下:
public int numberOf2sInRange(int n) {
int count =0;
long factor=1;
long low=0;
long cur=0;
long high=0;
while(n/factor!=0){
low = n - (n / factor) * factor;
cur = (n / factor) % 10;
high = n / (factor * 10);
if(cur<2){
count+=high*factor;
}else if(cur==2){
count+=(high*factor)+low+1;
}else{
count+=(high+1)*factor;
}
factor*=10;
}
return count;
}
LeetCode面试题43. 1~n整数中1出现的次数和本题思路一样,小伙伴们可以尝试一下。