疯狂整数的统计 | 豆包MarsCode AI刷题

69 阅读2分钟

题目总结笔记


问题描述

小C发现了一类特殊的整数,他称之为“疯狂整数”。疯狂整数是指只包含数字 '1' 和 '2' 的整数。举个例子,数字 12 和 121 都是疯狂整数。

现在,给定一个整数 N,你的任务是计算出所有小于或等于 N 的非负疯狂整数的数量。


测试样例

样例1:

输入:N = 21
输出:5

样例2:

输入:N = 50
输出:6

样例3:

输入:N = 5
输出:2


解题思路

  1. 特性分析

    • 疯狂整数的数字由 '1' 和 '2' 组成,可以通过递归生成所有可能的组合。
    • 数字从 1 和 2 开始,每次扩展时在末尾添加 '1' 或 '2'。
    • 递归或迭代可以很好地生成所有满足条件的疯狂整数。
  2. 方法选择

    • 使用 广度优先搜索 (BFS) 的方法:

      • 初始数字从 '1' 和 '2' 开始。
      • 不断扩展生成新的数字,直到所有生成的数字都大于 N。
      • 统计所有小于或等于 N 的疯狂整数。
  3. 剪枝优化

    • 当生成的数字大于 N 时,可以停止继续扩展,避免不必要的计算。

Java代码实现

import java.util.LinkedList;
import java.util.Queue;

public class Main {
    public static int solution(int N) {
        Queue<Integer> queue = new LinkedList<>();
        queue.offer(1);
        queue.offer(2);
        
        int count = 0;
        
        while (!queue.isEmpty()) {
            int current = queue.poll();
            if (current > N) {
                continue;
            }
            
            count++;
            
            queue.offer(current * 10 + 1);
            queue.offer(current * 10 + 2);
        }
        
        return count;
    }

    public static void main(String[] args) {
        System.out.println(solution(21) == 5); // 测试样例 1
        System.out.println(solution(50) == 6); // 测试样例 2
        System.out.println(solution(5) == 2);  // 测试样例 3
    }
}

代码解析

  1. 队列初始化

    • 初始化一个队列,初始值为 12,分别表示数字 '1' 和 '2'。
  2. BFS 生成数字

    • 每次从队列中取出一个数字 current,如果 current > N,停止处理该数字。
    • 如果 current≤Ncurrent \leq N,将其计入疯狂整数数量。
    • 在数字末尾追加 '1' 或 '2',生成新数字并加入队列。
  3. 统计并返回

    • 最后返回计数器 count 的值,即所有小于或等于 N 的疯狂整数的数量。

复杂度分析

  1. 时间复杂度

    • 每个数字扩展时生成两个新数字,生成的数字数量为 O(2^d),其中 d 是 N 的位数。
    • 时间复杂度为 O(2^d)。
  2. 空间复杂度

    • 队列中最多存储 O(2^d) 个数字。
    • 空间复杂度为 O(2^d)。

总结

  • 本题通过 BFS 方法生成所有满足条件的疯狂整数,并使用剪枝优化降低不必要的计算。
  • 代码逻辑清晰,易于扩展,可以适应更大的 N。