动态规划 - 2出现的次数 - 困难 - 再尝试

*************

C++

topic:面试题 17.06. 2出现的次数 - 力扣(LeetCode)

*************

看题:

还稍微理解了一下:

输入 13

那么在13前面的数字:

1 2 3 4 5 6 7 8 9 10 11 12 13

出现2的数字有 2 和 12,

其中,2 出现了2次。

又想暴力美学了,aesthetic of violent。

第一想法,2 ^ 10 = 1024,非常的搞笑,没有任何的相关性。

有突然想到,汤家凤老师说过,一个非常高级的骂人的话就是 你们都线性相关。

 0 ~ 9 出现 1 次2;

10 ~19 出现 1 次2;

20 ~ 29 出现 10 + 1 次2;

30 ~ 39 出现 1 次2;

40 ~49 出现 1 次2;

50 ~ 59 出现 1 次2;

等等,如果只有1个数字,判断给定的这个数字中有多少个2,会是怎么样呢?

首先对10位取余数 n%10 , if == 2, count

接着 n / 10

再循环

int countTwosInNumber(int num) {
        int count = 0;
        while (num != 0) {
            if (num % 10 == 2) {
                count++;
            }
            num = num / 10;
        }
        return count;
    }

那么,对n前面的每一个数字进行计算,只需要加一个循环:

class Solution {
public:
    int numberOf2sInRange(int n) {
        int totalTwos = 0;
        for (int i = 0; i <= n; i++) {
            totalTwos += countTwosInNumber(i);
        }
        return totalTwos;
    }
    
    int countTwosInNumber(int num) {
        int count = 0;
        while (num != 0) {
            if (num % 10 == 2) {
                count++;
            }
            num = num / 10;
        }
        return count;
    }
};

结果,不出意外的,超时,但是结果是可以运行的,这个代码是OK的。

屎上雕花,尿中浣溪沙。 

睡了个午觉,有了新的感想,一直喜欢简约的事情,喜欢一切聪明的人和事情。

换个方法,直接把所有的数字列出来,转换成字符串,寻找等于2的字符,输出:

class Solution {
public:
    int numberOf2sInRange(int n) {
        int count = 0;
        for(int i = 0; i <= n; i++) {
            string s = to_string(i);
            for(char c : s) {
                if(c == '2') {
                    count++;
                }
            }
        }
        return count;
    }
};

结果还是一样的,可以运行但是超时。

重新想个办法,需要写一个方法来计算从0到n(包括n)中数字2出现的次数。

输入是25,输出是9,解释是2,12,20,21,22,23,24,25,其中22出现了两次。

理解这个问题。要计算每一位上数字2出现的次数,然后把所有位上的次数加起来。

具体来说,假设有一个数,有d位,从个位开始,逐位计算2出现的次数。

比如说,对于十位数,计算十位上2出现的次数。

需要找出在每一位上,数字2出现的次数,然后加起来。

比如n=25,是两位数。

需要分别计算个位和十位上2出现的次数。

对于个位:

从0到25,个位上2出现的次数是:2,12,22,共3次。

对于十位:

从0到25,十位上2出现的次数是:20,21,22,23,24,25,共6次。

所以总共是3 + 6 = 9次,和示例一致。

所以,怎么找一个通用的方法,来计算每一位上的2出现的次数呢?

让我参考一下别人的思路,

设当前位是第k位(从右开始,个位是第0位),n的第k位数字是current, cur for short,高位数字是high,低位数字是low。

ihighklow0
n1cur13

那么:

看不懂,直接放弃,下周一再说吧,真有点难。

下面是抄的代码:

class Solution {
public:
    int numberOf2sInRange(int n) {
        int count = 0;
        int factor = 1;  // 当前位的权值,初始为个位
        while (factor <= n) {
            int high = n / (factor * 10);      // 高位数字
            int current = (n / factor) % 10;   // 当前位数字
            int low = n % factor;              // 低位数字
            
            if (current < 2) {
                count += high * factor;
            } else if (current == 2) {
                count += high * factor + low + 1;
            } else {
                count += (high + 1) * factor;
            }
            
            factor *= 10;  // 移动到下一位
        }
        return count;
    }
};

跟数学沾边的东西,确实有点难。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值