问题描述
相传在古印度圣庙中,有一种被称为汉诺塔(Hanoi)的游戏。该游戏是在一块铜板装置上,有三根杆(编号A、B、C),在A杆自下而上、由大到小按顺序放置64个金盘(如图)。游戏的目标:把A杆上的金盘全部移到C杆上,并仍保持原有顺序叠好。操作规则:每次只能移动一个盘子,并且在移动过程中三根杆上都始终保持大盘在下,小盘在上,操作过程中盘子可以置于A、B、C任一杆上。
思路
把n个盘子的问题简化成2个盘子的问题。当2个盘子和3个柱子时,问题很好解决,因此可以把所有盘子分成两块:顶部的n-1个盘子作为一个整体,第n个盘子作为一个整体,这就抽象成了2个盘子的模型。
这样的话我们便可以使用递归的方法来反复模拟两个盘子的情况。
为什么使用 " 顶部 n-1 个盘子 和 底部 1 个盘子 " 的划分策略 ? 为什么不用 " 顶部 1 个盘子 和 底部 n-1 个盘子 " 的划分策略 ?
实现
# n : n个盘子
# a,b,c : 柱子编号
# 每次从 a b c 柱子的顶部移动一个盘子
# 描述: 把顶部的n个盘子,从a经过b移动到c
def hanoi(n,a,b,c):
if(n>0):
hanoi(n-1,a,c,b)
print("moving from %s to %s" % (a,c))
hanoi(n-1,b,a,c)
if __name__ == "__main__":
hanoi(2,'a','b','c')
或者
def func(n,start,interval,end):
if n<1:
return
func(n-1,start,end,interval)
print("move" + str(n) + " from " + str(start) + " to " + str(end))
func(n-1,interval,start,end)
func(3,"a","b","c")
'''
move1 from a to c
move2 from a to b
move1 from c to b
move3 from a to c
move1 from b to a
move2 from b to c
move1 from a to c
'''
事件复杂度:
共需要移动 h(x) = 2h(x-1) + 1 次
时间复杂度约等于 O(2^n)