Python3的简单递归问题
一些简单递归问题的思路
看了林信良老师的书重新写了这些东西,说起来python完成这些东西相当有趣呢
1.hanoi(汉诺塔问题)
汉诺塔问题应该是递归的入门问题,很多人(我和我的小伙伴)都是从汉诺塔问题开始学习递归的思路。(多年前在课堂苦苦思索汉诺塔的日子,是我逝去的青春——sad)
def movit(num,X,Y,Z):
if num == 1:
print(X,'->',Z)
else:
movit(num-1,X,Z,Y)
print(X,'->',Z)#movit(1,X,Y,Z),有些人是这么用的
movit(num-1,Y,X,Z)
movit(3,'x','y','z')#测试用例
对于每一个碟片,我们只需要移动它到目标点就好了。
多层次的移动可以看作是三个部分:
- 移动在起点的上部分(n-1个)碟片到暂存点,其中可能有多个,所以我们将其描述为X通过Z移动到Y。(X->Z->Y)
- 移动最下面的碟片到目标点位,即为(X->Z),因为只有一片,直接移动过去就好了。
- 将刚刚第一步中,移动到Y的那部分移动到目标点,,即为(Y->X->Z)
每一个多层次都可以看作是多个单个碟片的移动,相当有趣。
2.八皇后问题
八皇后问题也十分有趣,但是究其思路其实非常简单,当你做出他的时候,可能会疑惑为什么自己花了相当长时间在这个问题上面。
def isSafe(q,qs):
return all(not checkSame(q,q1) for q1 in qs)
def checkSame(q1,q2):
return (q1[0] == q2[0] or # 同行
q1[1] == q2[1] or # 同列
abs(q1[0] - q2[0]) == abs(q1[1] - q2[1])) # 对角线
def printQueens(qs):
chess = [
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0]
]
for q in qs:
chess[q[0]-1][q[1]-1] = 1
for row in chess:
for pt in row:
print(' Q' if pt else ' .',end = '' )
print()
def putall(n):
def put(k):
return [[]] if k == 0 else [[(k,col)] + lastReturns
for lastReturns in put(k-1)
for col in range(1,n+1)
if isSafe((k,col),lastReturns)]
return put(n)
for qs in putall(8):
printQueens(qs)
print()
我们知道饭要一口一口吃,棋子也是一颗一颗放。
整个八皇后问题其实只是简单的遍历的操作,但在python的实现上就变得相当的有趣了。
下面是注意事项(readme):
- 从下往上,让八个皇后乖乖站好只需要叫他们出来,然后再打出在屏幕上就好了,
qs
是每八个皇后。- 再实现产生
qs
的方法putall()
,该函数需要产生一个八列的二维数组,每一个一维数组存放qs
。
- 完成每一次合理的八皇后,都需要一个一个的放棋子。
- 对于第n个下的棋子,需要对前面n-1个棋子比较位置,是否可以下这个位置,若不是,那么不下。
- 下第一个棋子,不需要对前面棋子比较。
3.骑士周游问题
骑士周游问题在我看来比上述问题稍微麻烦一点(我才不是懒得写代码了)
我们将其当作是下64个骑士棋子(其实没啥区别),这样更容易理解我的思路:
第一个棋子用户输入,没啥好说的。
对于第n个棋子,他都有八个方向可以走,而下一个棋子同样是。
- 每一次下棋事件,如果找不到可以下的位置,则
break
。 - 如果只有一个可以下的位置,那么直接下。
先下难下的位置,然后再下容易下的位置,这是一个数学问题,而我(
也不知道为什么)讨厌解释数学问题
- 如果有多个可以下的位置,那么探索所有可以下的点,将当前点存放在写的栈中,然后找到所有可以下的点的所有路径数。loop
代码?什么代码?我为什么要写这玩意?马上吃饭了
4.思考
递归:
扫描二维码关注公众号,回复:
10779887 查看本文章
- 描述第一个点
- 再描述第n个点