LeetCode.剑指offer.046.把数字翻译成字符串
题目描述
《剑指offer》面试题46. 把数字翻译成字符串
https://leetcode-cn.com/problems/ba-shu-zi-fan-yi-cheng-zi-fu-chuan-lcof/
给定一个数字,我们按照如下规则把它翻译为字符串:0 翻译成 “a” ,1 翻译成 “b”,……,11 翻译成 “l”,……,25 翻译成 “z”。一个数字可能有多个翻译。请编程实现一个函数,用来计算一个数字有多少种不同的翻译方法。
示例 1:
输入: 12258
输出: 5
解释: 12258有5种不同的翻译,分别是"bccfi", "bwfi", "bczi", "mcfi"和"mzi"
提示:0 <= num < 2^31
解题过程
回溯法
看到这个题第一反应就是回溯,类似 排列 或 子集 问题,选择 1位数 或 2位数 进行转换,然后递归的进行后续转换并撤销选择,直到数字为0,加入结果集,写了一版,能通过。
注意 0 前缀需要被忽略,比如 100001 的翻译方案共有 2 种: [bb, kb],中间的 0 不能单独翻译,比较奇怪。
回溯法复杂度不好分析,时间复杂度也是很高的。
private static class SolutionV202006BackTracking {
Set<String> res;
public int translateNum(int num) {
res = new HashSet<>();
backtrack(String.valueOf(num), new LinkedList<>());
System.out.println(res);
return res.size();
}
// 回溯法
private void backtrack(String num, LinkedList<Integer> choice) {
// 去掉前导0
while (!num.equals("") && num.charAt(0) == '0') {
num = num.substring(1);
}
// 到达叶子节点,放入结果集
if (num.equals("")) {
StringBuilder sb = new StringBuilder();
for (int i : choice) {
sb.append((char)(i + 'a'));
}
res.add(sb.toString());
return;
}
// 选1位数
choice.offerLast(num.charAt(0) - '0');
backtrack(num.substring(1), choice);
choice.pollLast(); // 回溯,撤销选择
// 选2位数
if (num.length() >= 2 && (num.charAt(0) < '2' || (num.charAt(0) == '2' && num.charAt(1) < '6'))) {
choice.offerLast((num.charAt(0) - '0') * 10 + num.charAt(1) - '0');
backtrack(num.substring(2), choice);
choice.pollLast(); // 回溯,撤销选择
}
}
}
动态规划
dp[i]
表示以 num[i] 为结尾的数字的翻译方案数量。
若 nums[i] 和 nums[i-1] 组成的 2 位数可以被翻译,也就是在 [10, 25] 之间,则 dp[i] = dp[i-1] + dp[i-2]
,注意 01 … 09 无法被翻译
否则 dp[i] = dp[i-1]
初始条件 dp[0] = 1, dp[1] = 1,即 无数字 和 1 位数字的翻译方案数都是 1
GitHub代码
algorithms/leetcode/offer/_046_TranslateNumToString.java
https://github.com/masikkk/algorithms/blob/master/leetcode/offer/_046_TranslateNumToString.java
上一篇 LeetCode.739.Daily Temperatures 每日温度
下一篇 LeetCode.990.Satisfiability of Equality Equations 等式方程的可满足性
页面信息
location:
protocol
: host
: hostname
: origin
: pathname
: href
: document:
referrer
: navigator:
platform
: userAgent
: