一、递归应用-十进制转换任意进制
一个十进制整数,实现从二进制到十六进制的任意进制转换。采用递归三定律分析:
- 用整数除和求余数,两个计算来将任意十进制数一步步拆开。除以“进制基base”(// base)得到商,对“进制基”求余数(% base)
- 基本结束条件:余数总小于“进制基base”,是“基本结束条件”,可直接进行查表转换
- 减少问题规模并调用自身:商成为“更小规模”问题,通过递归调用自身解决
def decimal_to_base(decimal_number, base):
digits = "0123456789ABCDEF"
if decimal_number < base:
return digits[decimal_number]
else:
# +号实现字符串拼接,两者顺序不能互换
return (
decimal_to_base(decimal_number // base, base)
+ digits[decimal_number % base]
)
print(decimal_to_base(60, 2))
print(decimal_to_base(60, 8))
print(decimal_to_base(60, 16))
### 输出结果
111100
74
3C
二、递归应用-汉诺塔
汉诺塔
- 汉诺塔问题是法国数学家Edouard Lucas于1883年,根据传说提出来的
- 有3根柱子,其中一根套着64个由小到大的黄金盘片,要把这一叠黄金盘从一根柱子搬到另一根,但有两个规则:
- 一次只能搬1个盘子
- 大盘子不能叠在小盘子上
分析
- 假设我们有5个盘子,穿在1#柱,需要挪到3#柱
- 想办法把最上面4个盘子挪到2#柱,那问题就好解决了:把剩下的最大号盘子直接从1#柱挪到3#柱。再用同样的办法把2#柱上的4个盘子挪到3#柱,就完成了整个移动
- 接下来问题就是解决4个盘子如何能从1#挪到2#?此时问题规模已经减小!
- 想办法把最上面3个盘子挪到3#柱,把剩下最大号盘子从1#挪到2#柱。再用同样的办法把3个盘子从3#挪到2#柱
- 接下来问题就是解决3个盘子如何能从1#挪到3#?此时问题规模已经减小!
- 想办法把最上面2个盘子挪到2#柱,把剩下最大号盘子从1#挪到3#柱。再用同样的办法把2个盘子从2#挪到3#柱
- 接下来问题就是解决2个盘子如何能从1#挪到2#?此时问题规模已经减小!
- 把最上面1个盘子挪到3#柱,把剩下最大号盘子从1#挪到2#柱。再把1个盘子从3#挪到2#柱
递归思路
- 将盘片塔从开始柱,经由中间柱,移动到目标柱:
- 首先将上层N-1个盘片的盘片塔,从开始柱,经由目标柱,移动到中间柱;然后将第N个(最大的)盘片,从开始柱,移动到目标柱;最后将放置在中间柱的N-1个盘片的盘片塔,经由开始柱,移动到目标柱。
- 基本结束条件,也就是最小规模问题是:1个盘片的移动问题
### 汉诺塔问题
def move_tower(level, from_pole, with_pole, to_pole):
if level > 0: # 结束条件
# 上层N-1个盘片的盘片塔,从开始柱,经由目标柱,移动到中间柱
move_tower(level - 1, from_pole, to_pole, with_pole) #
# 将第N个(最大的)盘片,从开始柱,移动到目标柱
move_disk(level, from_pole, to_pole)
# 将放置在中间柱的N-1个盘片的盘片塔,经由开始柱,移动到目标柱
move_tower(level - 1, with_pole, from_pole, to_pole