算法—2,记一个自己的算法题 计算数字k在0到n中的出现的次数,k可能是0~9的一个值

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)

AC

int countDigitOne(int n, int k) {
    if (n<10 &&k==0) {
        return 1;
    }
    int sum =0;
    int level = 1;
    while(n / level != 0){
        if (k == 0 && n / (level * 10) == 0) {// 最高位不能为0
            break;
        }
        int cur = (n/level) %10;//计算当前位
        int bef = n/(10*level);//计算当前位高位
        int aft = n - n/level *level;//计算当前位的低位
        if (cur >k) {
            sum += (bef+1)*level;
        }else if (cur <k) {
            sum += (bef)*level;
        }else{
            sum += (bef)*level +aft+1;
        }
        level*= 10;
    }
    return sum;
}

这道算法题其实算不上难,但是我的思路却一直限制了我,走了一些弯路,实在不应该。

首先看这道算法题,计算出现的次数,我们可以看一个例子来理解这道题。

如123中出现的2的次数。

首先123中出现了多少次2,我们可以这么想,个位有多少个2,十位有多少个2,百位有多少2。

1,个位有多少2呢?因为3是大于2的,所以2 12 22 32 42…122一共有12 +1 个,我们可以想象,如果个位的3小于2,那么就只有12个了,最后一个12X上不会有。如果等于呢 则也是12+1。

2,十位有多少2呢? 因为2 ==2 ,所以 21 22 23 24 25…29 120 121 122,这里可以看出来加入十位大于2的时候,则会有 20个,如果小于2,则10个,如果等于,则是10 + 个位+1 (因为个位是2,而计数从0开始 ,如这里加的这个1是120这个)

这里我们可以进行总结:

如果 当前位大于k,则 (高位+1)乘 当前的计数级别(个位为1,十位为10,百位为百)

如果当前位小于k, 则 为高位 乘 当前的计数级别。

如果等于,则为 高位数 乘 当前计数级别 + 低位数+1。

这里的难点就只剩下怎么计算这个当前位,怎么计算当前位的高位,怎么计算当前位的低位。

例如123 ,如果要计算十位的高位,低位,当前位。

当前位:123/10(计数级别) %10(固定10) = 12%10 = 2

高位: 123/(10(固定10) * 10(计数级别))

低位: 123 - 123/10(计数级别)*10(计数级别)

整理一下就是

        int cur = (n/level) %10;//计算当前位
        int bef = n/(10*level);//计算当前位高位
        int aft = n - n/level *level;//计算当前位的低位

猜你喜欢

转载自blog.csdn.net/doujinlong1/article/details/81366217