leetcode
leetcode 2851 ~ 2900
2出现的次数

2出现的次数

难度:

标签:

题目描述

Write a method to count the number of 2s that appear in all the numbers between 0 and n (inclusive).

Example:

Input: 25
Output: 9
Explanation: (2, 12, 20, 21, 22, 23, 24, 25)(Note that 22 counts for two 2s.)

Note:

  • n <= 10^9

代码结果

运行时间: 27 ms, 内存: 16.1 MB


/*
 * 思路:
 * 1. 使用 IntStream 生成从 0 到 n 的范围。
 * 2. 将每个数字转换为字符串,并计算每个字符串中 '2' 出现的次数。
 * 3. 使用 sum() 方法累加所有次数。
 */

import java.util.stream.IntStream;

public class CountTwosStream {
    public static int countTwos(int n) {
        return IntStream.rangeClosed(0, n)
                .mapToObj(Integer::toString)
                .flatMapToInt(num -> num.chars().map(c -> c == '2' ? 1 : 0))
                .sum();
    }

    public static void main(String[] args) {
        int n = 25;
        System.out.println(countTwos(n)); // 输出:9
    }
}

解释

方法:

这个题解采用了数位分析的方法来统计数字2的出现次数。首先,对于给定的数字n,算法逐位考察(从个位开始到最高位),并计算每一位上数字2出现的总次数。具体来说,对于每一位,算法分别计算这一位上的数字(curr)、其低位组成的数字(low)和高位组成的数字(high)。然后根据当前位的数字分三种情况处理:1) 当前位数字小于2时,2的数量由高位数字决定;2) 当前位数字等于2时,2的数量由高位和低位共同决定;3) 当前位数字大于2时,高位数字增加一的情况也需要计入2的总数。这种方法利用数学分割和模运算来避免直接的枚举,从而提高效率。

时间复杂度:

O(log(n))

空间复杂度:

O(1)

代码细节讲解

🦆
在处理数位时,算法是如何确保从个位开始逐位向高位处理的?
在算法中,`factor`变量起着关键作用,其初始值为1,表示最低位(个位)。通过逐次乘以10,`factor`依次表示十位、百位、千位等,确保了从个位开始,逐位向高位处理。在每次循环中,通过计算`(n // factor) % 10`可以得到当前位的值。循环的继续条件是`n // factor > 0`,意味着只要除以`factor`的结果大于0,就表示还有更高的位需要处理。这样,算法从个位开始,一直处理到最高位。
🦆
如果当前位的数字等于2,为什么在计算2的出现次数时需要将低位数字加1?
当当前位的数字等于2时,除了考虑高位数字能形成的所有可能组合外,还需要考虑低位数字能形成的所有可能性。例如,假设数字为`XYZ2ABC`,其中`2`是我们正在处理的位,`XYZ`是高位,`ABC`是低位。在这种情况下,所有`XYZ`高位的组合已经计算(即`XYZ * factor`),但对于每一种`XYZ`的组合,低位可以从`000`到`ABC`(包括`ABC`本身),因此需要加上`ABC + 1`(即低位的数字总数)。这样我们就能确保包含了所有以2为当前位的数字组合。
🦆
算法中的factor变量有什么作用,它是如何帮助确定当前处理的是哪一位数字的?
`factor`变量在算法中表示当前处理的数位的基数(例如个位的基数是1,十位是10,百位是100等)。通过不断地将`factor`乘以10,可以移动到下一个更高的数位。在计算当前位的数字时使用`(n // factor) % 10`,这样便能得到从个位开始逐位的数值。同时,`factor`也用于计算高位和低位的数值,高位用`n // (factor * 10)`计算,而低位则是`n - (n // factor) * factor`。这样,`factor`帮助算法理解并分析每一位数的值及其对最终数位中2的出现次数的贡献。

相关问题