题目
给定一个数字,我们按照如下规则把它翻译为字符串:
0 翻译成 “a” ,1 翻译成 “b”,……,11 翻译成 “l”,……,25 翻译成 “z”。
一个数字可能有多个翻译。请编程实现一个函数,用来计算一个数字有多少种不同的翻译方法。
示例 1:
输入: 12258 输出: 5
解释: 12258有5种不同的翻译,分别是"bccfi", “bwfi”, “bczi”,“mcfi"和"mzi”
提示:
0 <= num < 2^31
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/ba-shu-zi-fan-yi-cheng-zi-fu-chuan-lcof
解题思路
-
解法一:回溯递归
-
绝大部分树形问题(多叉树或者是二叉树)都可以通过回溯解决,
-
这道题抽象为树模型后就是:求一颗二叉树从根结点到达叶节点的路径总数。
-
因为每次可能的选择都只有两个,犹如二叉树的两个分支。
-
如对于数字 13( 在 0 ~ 25 的范围内 ):
- 可以只选择一位,也就是 1 ,翻译成字符就是 b;
- 也可以两位都选,也就是 13 , 翻译成字符为 n。
-
-
所以最多就只有两个选择:
- 走左子树或走右子树,走到叶子结点就返回 1 ,代表这条路径可以到达终点。
-
解题思路引用自作者:huwt
-
解法二:斐波那契变种(爬楼梯)
- 爬楼梯
- 爬 n 层楼,爬楼梯时每次可以爬一层或两层,求有多少种不同的方法到达楼顶?
- 同理,这道题则变成了
- 有一串数字,每次可以选择一个数字或两个数字,用来合并成一个字符,求可以合成多少种字符串?
- 有一串数字,每次可以选择一个数字或两个数字,用来合并成一个字符,求可以合成多少种字符串?
- 爬楼梯
-
注意:数字可被翻译为字符串的范围是 0 ~ 25 对应 ‘a’ ~ 'z’
解法一:回溯递归
–执行用时:0 ms --内存消耗:1.9 MB
func translateNum(num int) int {
str := strconv.Itoa(num)
if len(str) == 0{
return 0
}
return backtrace(str,0)
}
func backtrace(str string,pos int)int {
n := len(str)
if pos == n{
return 1
}
if pos == n-1 || str[pos] == '0' || str[pos:pos+2] > "25"{
return backtrace(str,pos + 1)
}
return backtrace(str,pos + 1) + backtrace(str,pos + 2)
}
解法二:斐波那契变种
–执行用时:0 ms --内存消耗:1.9 MB
func translateNum(num int) int {
str := strconv.Itoa(num)
if len(str) == 0{
return 0
}
dp := make([]int, len(str)+1)
dp[0] = 1
dp[1] = 1
for i := 1;i < len(str); i++{
if str[i - 1] == '0' || str[i - 1:i + 1] > "25"{
dp[i + 1] = dp[i]
}else{
dp[i + 1] = dp[i] + dp[i - 1]
}
}
return dp[len(str)]
}