3. 统计数字

计算数字k在0到n中的出现的次数,k可能是0~9的一个值

样例 例如n=12,k=1,在 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],我们发现1出现了5次
(1, 10, 11, 12)

这道题主要用一般方法,当然暴力是可以的,但是时间复杂度太高

首先来看一个例子:n=2169,k=1,我们从低位到高位来看:

首先是个位9:
9前面有216个10,故有216个1,又因为9>1,所以一共有216+1=217个1

然后是十位6:
6前面有21个100,100中有10个1,故有21*10=210个1,又因为6>1,所以包含了10~19的十个1,一共有210+10=220个1

然后是百位1:
1前面有2个1000,1000中有100个1,故有2*100=200个1,这里1==1,也就是多了100~169一共69+1=70个1,一共有200+70=270个1

然后是千位2:
2>1,包含了1000~1999的999+1=1000个1

一共有
217+220+270+1000=1707个1

但是k=0时的情况不同,还是以n=2169,k=0为例

首先是个位9:
不变

然后是十位6:
6>0,但00~09的情况不存在,结果-10

然后是百位1:
6>0,但000~099的情况不存在,结果-100

然后是千位2:
6>0,但0000~0999的情况不存在,结果-1000

但是0000的情况可以存在
一共有
1737-1110=627种情况

因此,算法如下
当计算从右往左数第 i位包含 k 的个数时:

若第i位大于k,则结果为第i位左边所有数字乘以10的i-1次方+10的i-1次方
若第i位小于k,则结果为第i位左边的所有数字乘以10的i-1次方
若第i位等于k,则结果为第i位左边所有数字乘以10的i-1次方+右边的所有数字+1

代码如下

int digitCounts(int k, int n)
{
    int bit=1;//当前位的权重
    int bitnum=0;//当前位的具体数字
    int sum=0;//k出现的总次数
    int val=n;//赋值val用于计算每位
    int t=0;//处理k=0时候的情况,t为要减去的情况之和
    if(n==k)
        return 1;
    while(val!=0)
    {
        bitnum=val-(val/10)*10;
        if(bitnum<k)
            sum+=(val/10)*bit;
        else if(bitnum==k)
            sum+=(val/10)*bit+n-val*bit+1;
        else
            sum+=(val/10)*bit+bit;
        t+=bit;
        bit*=10;
        val/=10;
        cout<<sum<<" "<<val<<endl;
    }
    if(k==0)
    {
        sum-=(t-1);//减1是去掉bit为1时的情况,即0的情况存在
    }
    return sum;
}

猜你喜欢

转载自blog.csdn.net/weixin_42316707/article/details/86510114
今日推荐