1. 题目
给定一个数字,我们按照如下规则把它翻译为字符串:0 翻译成 “a” ,1 翻译成 “b”,……,11 翻译成 “l”,……,25 翻译成 “z”。一个数字可能有多个翻译。请编程实现一个函数,用来计算一个数字有多少种不同的翻译方法。
2. 解题思路
详情见 面试题46. 把数字翻译成字符串(动态规划,清晰图解)
2.1 递归
自顶向下
举例,输入数字 1068385920
由于末尾的20可以看做单独的2和0,也可以看做20,也就是说 ‘1068385920’ = ‘106838592’ + ‘0’ + ‘10683859’ + ‘20’
所以,f(1068385920) = f(106838592) + f(10683859)
若是 1068385930,那么 f(1068385930) = f(106838593)
在10~25这个范围内的数有两种分配方法,不在这个范围的数只有一种分配方法
按照这个规律递归下去就行了。
2.2 迭代(动态规划)
自底向上,根据初始条件和递推公式推到下一个状态的结果。
有些类似于前面的青蛙跳台阶问题。
在10~25这个范围内的数有两种分配方法,不在这个范围的数只有一种分配方法
a, b = 1, 1
if 10 <=num<=25
a, b = b, a+b
else:
a, b = b, b
3. 代码实现
3.1 递归
当然也可以用字符串来递归,不过数字的更佳。
class Solution:
def translateNum(self, num: int) -> int:
"""
递归
"""
if 0 <= num <= 9: return 1
a = num % 100
if 10 <= a <= 25:
return self.translateNum(num//100) + self.translateNum(num//10)
else:
return self.translateNum(num//10)
3.2 字符串遍历
当然也可用从右往左遍历,结果是一样的。
class Solution:
def translateNum(self, num: int) -> int:
s = str(num)
a = b = 1
for i in range(2, len(s) + 1):
tmp = s[i - 2:i]
c = a + b if "10" <= tmp <= "25" else a
b = a
a = c
return a
3.3 数字求余
通过数字求余使用更少的空间。
class Solution:
def translateNum(self, num: int) -> int:
a = b = 1
y = num % 10
while num != 0:
num //= 10
x = num % 10
tmp = 10 * x + y
c = a + b if 10 <= tmp <= 25 else a
a, b = c, a
y = x
return a
4. 总结
通常,遇见数字相关的算法,最好用求余、商等操作,实在不行再转成字符串来处理。
5. 参考文献
[1] 剑指offer丛书
[2] 剑指Offer——名企面试官精讲典型编程题