leetcode
leetcode 201 ~ 250
中心对称数 II

中心对称数 II

难度:

标签:

题目描述

代码结果

运行时间: 43 ms, 内存: 26.5 MB


/*
 * 题目思路:
 * 中心对称数是指一个数字旋转180度之后看起来还是一样的数字。
 * 比如数字 '69' 旋转180度之后是 '96',数字 '88' 旋转180度之后是 '88'。
 * 要求找出所有长度为 n 的中心对称数。
 * 
 * 解题步骤:
 * 1. 递归生成长度为 n 的所有中心对称数。
 * 2. 定义两个字符数组,分别用于存储可以构成中心对称数的字符对。
 * 3. 使用递归函数生成中心对称数。
 * 4. 处理基准情况和递归情况,保证生成的数是有效的中心对称数。
 */
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
 
public class StrobogrammaticNumberIIStream {
    public List<String> findStrobogrammatic(int n) {
        return helper(n, n).collect(Collectors.toList());
    }
 
    private Stream<String> helper(int n, int m) {
        if (n == 0) return Stream.of("");
        if (n == 1) return Stream.of("0", "1", "8");
 
        return helper(n - 2, m).flatMap(s -> Stream.of(
                n != m ? "0" + s + "0" : "",
                "1" + s + "1",
                "6" + s + "9",
                "8" + s + "8",
                "9" + s + "6"
        )).filter(s -> !s.isEmpty());
    }
 
    public static void main(String[] args) {
        StrobogrammaticNumberIIStream solution = new StrobogrammaticNumberIIStream();
        System.out.println(solution.findStrobogrammatic(2));
    }
}
 

解释

方法:

这个题解使用了深度优先搜索(DFS)的思路来生成中心对称数。首先,对于长度为0和1的中心对称数,直接返回对应的结果。对于长度大于1的中心对称数,通过递归生成长度减2的中心对称数,然后在两边添加对称的数字对(11、88、69、96)得到新的中心对称数。特别地,如果当前生成的中心对称数长度不等于目标长度n,还可以在两边添加00得到新的中心对称数。最终返回长度为n的所有中心对称数。

时间复杂度:

O(5^(n/2))

空间复杂度:

O(n * 5^(n/2))

代码细节讲解

🦆
在解决这个问题时,为什么选择使用深度优先搜索(DFS)而不是其他可能的算法,例如广度优先搜索(BFS)或动态规划?
深度优先搜索(DFS)适用于这个问题,因为我们需要探索所有可能的中心对称数组合,直到达到指定的长度。DFS允许从内部向外递归构建对称数,从中心开始向两端扩展,这种自顶向下的构建方法在逻辑上更直观。相对于BFS,DFS在这种情况下可以更自然地遵循生成对称数的递归模式。而动态规划不适用于这种类型的问题,因为中心对称数的生成不涉及到子问题的最优解决策略,而是单纯的组合生成。
🦆
在递归函数中,将'00'添加到结果中只在`u != n`的条件下进行。这是基于什么考虑?是否是为了避免在生成最终长度为n的中心对称数时出现以0开头的非法数字?
正确,这个条件是为了避免生成的中心对称数以0开头,因为在大多数数字表示中,以0开头的数字是不合法或不符合预期的(例如,'01'通常被视为简单的'1')。如果在长度等于n的最终结果中包含以0开头的数字对,这将导致不正确或无效的输出。因此,这个条件确保只有在生成中间步骤的较短数字时才添加'00',而在生成最终长度的数字时不会添加以0开头的组合。
🦆
题解提到,中心对称数的生成依赖于添加对称的数字对(11、88、69、96),那么在选择这些对称的数字对时,有没有考虑到它们在数学或编程上的特殊性质,这些性质是什么?
这些对称的数字对被选择是因为它们在旋转180度后可以保持视觉上的对称性。例如,'88'旋转后仍然是'88',而'69'和'96'旋转后会变成彼此。这是中心对称数的基本要求,即数字旋转180度后应该看起来与原数字相同或成为对应的另一个数字。在数学或编程上,这些对没有特别的性质,它们只是单纯满足视觉上的对称要求。
🦆
在实际实现中,递归深度为O(n)可能会导致栈溢出。有没有可能的优化策略来减少递归的深度或是完全避免递归?
为了减少递归深度或完全避免递归,可以使用迭代方法来生成中心对称数。具体来说,可以从已知的最小长度中心对称数开始,如长度为0和1的情况,然后迭代地向这些数的两端添加对称的数字对来构造更长的数字。这种方法利用循环而非递归,通过维护一个当前所有可能结果的列表,并在每次迭代中更新这个列表,直到达到目标长度。这样可以有效避免递归导致的栈溢出问题。

相关问题

中心对称数

中心对称数

中心对称数 III

中心对称数 III