题目来源:🔒LeetCode248:中心对称数 III
问题抽象: 计算给定数值区间内所有中心对称数的数量(旋转 180° 后数值不变),需满足以下核心需求:
-
对称规则与数值范围:
- 中心对称数定义:由
'0','1','6','8','9'组成,且满足'0'↔'0','1'↔'1','6'↔'9','8'↔'8'的旋转映射; - 目标区间:闭区间
[low, high](输入为字符串,可能超过 64 位整数范围); - 无前导零约束(如
"0690"无效,因首字符'0')。
- 中心对称数定义:由
-
高效计数策略:
- 采用 DFS 生成 + 剪枝:
- 按长度分层生成对称数(从
len(low)到len(high)); - 仅构造满足区间约束的数值(构造时比较字符串避免溢出);
- 按长度分层生成对称数(从
- 剪枝关键:
- 当前缀已超出区间范围时终止生成;
- 跳过含前导零的无效构造(首字符仅限
'1','6','8','9')。
- 采用 DFS 生成 + 剪枝:
-
边界处理:
- 单字符对称数:仅
"0","1","8"("0"需特殊处理,避免作为多位数前缀); - 区间包含性:
low和high为闭区间端点,需包含有效对称数; - 大数处理:输入字符串长度可能达 100 位,不可转数值计算。
- 单字符对称数:仅
输入:两个数字字符串 low, high(1 ≤ len(low), len(high) ≤ 100,且 low ≤ high)
输出:整数(区间内有效中心对称数的数量)。
解题思路
中心对称数的生成规则:
- 基础对称对:
{0,0},{1,1},{6,9},{8,8},{9,6}。 - 中间字符(奇数长度时):只能是
0,1,8。 - 避免前导零:生成的数字首位不能是
0(除非是单字符"0")。
高效生成策略(BFS剪枝):
- 初始化队列:包含空字符串、单字符(
"0","1","8")和双字符对称数("11","69","88","96")。 - 逐层扩展:
- 每次从队列取出一个数字,在其两侧对称添加字符对(如
6+原数字+9)。 - 若新数字长度超过
high的长度,则跳过(剪枝)。
- 每次从队列取出一个数字,在其两侧对称添加字符对(如
- 范围检查:
- 新数字长度在
[low.length(), high.length()]内时,检查是否在[low, high]区间。 - 若长度等于
high.length()且已超过high,停止扩展(剪枝)。
- 新数字长度在
- 去重与去无效零:跳过以
0开头的多位数。
代码实现(Java版)🔥点击下载源码
class Solution {
// 对称字符映射表
private static final char[][] PAIRS = {{'0','0'}, {'1','1'}, {'6','9'}, {'8','8'}, {'9','6'}};
public int strobogrammaticInRange(String low, String high) {
if (Long.parseLong(low) > Long.parseLong(high)) return 0;
int count = 0;
Queue<String> queue = new LinkedList<>();
// 初始化基础数字
Collections.addAll(queue, "", "0", "1", "8");
// 添加双字符对称数(排除"00")
for (char[] pair : new char[][]{{'1','1'}, {'6','9'}, {'8','8'}, {'9','6'}}) {
queue.add(String.valueOf(pair[0]) + pair[1]);
}
while (!queue.isEmpty()) {
String num = queue.poll();
// 剪枝:长度超过 high 或数值超过 high
if (num.length() > high.length() ||
(num.length() == high.length() && num.compareTo(high) > 0)) {
continue;
}
// 有效数字条件:非空 && 无前导零(除非是单字符"0")
if (!num.isEmpty() && (num.length() == 1 || num.charAt(0) != '0')) {
// 范围检查:num >= low 且 num <= high
if (num.length() > low.length() ||
(num.length() == low.length() && num.compareTo(low) >= 0)) {
count++;
}
}
// 扩展:两侧添加对称对(长度不超过 high)
if (num.length() + 2 <= high.length()) {
for (char[] pair : PAIRS) {
String newNum = pair[0] + num + pair[1];
queue.offer(newNum);
}
}
}
return count;
}
}
代码说明
- 对称对生成:
- 使用
PAIRS定义合法对称字符组合。 - 初始化队列包含空串、单字符和双字符对称数(跳过无效的
"00")。
- 使用
- 剪枝优化:
- 长度剪枝:若新数字长度超过
high.length(),跳过。 - 数值剪枝:若新数字长度等于
high.length()且值大于high,跳过。
- 长度剪枝:若新数字长度超过
- 范围检查:
- 使用
compareTo比较字符串形式的数字(避免大数溢出)。 - 检查
num是否满足low <= num <= high。
- 使用

560

被折叠的 条评论
为什么被折叠?



