一、递归的定义
程序调用自身的编程技巧称为递归( recursion)。
递归函数就是直接或间接调用自身的函数。
#直接调用自己:
def func():
print('from func')
func()
func()
#间接调用自己
def foo():
print('from foo')
bar()
def bar():
print('from bar')
foo()
foo()
二、递归经典例子
1、斐波那契数列
描述:斐波那契数列指的是这样一个数列 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233,377,610,987,1597,2584,4181,6765,10946,17711,28657,46368……..这个数列从第3项开始,每一项都等于前两项之和。
class Solution:
# 递归
def Fibonacci(self, n):
if n == 1:
return 1
return self.Fibonacci(n-1)+self.Fibonacci(n-2)
#非递归
def Fibonacci2(self, n):
a, b = 0, 1
for i in range(n):
a, b = b, a+b
return b
f = Solution()
print(f.Fibonacci(10))
print(f.Fibonacci2(10))
2、汉诺塔
描述:汉诺塔:汉诺塔(又称河内塔)问题是源于印度一个古老传说的益智玩具。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。
def move(n,a,b,c):
if n == 1:
print(a,'-->',c)
else:
move(n-1,a,c,b)
move(1,a,b,c)
move(n-1,b,a,c)
move(3,'a','b','c')
输出结果:
a --> c
a --> b
c --> b
a --> c
b --> a
b --> c
a --> c
3、八皇后
描述:八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例。该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。 高斯认为有76种方案。1854年在柏林的象棋杂志上不同的作者发表了40种不同的解,后来有人用图论的方法解出92种结果。计算机发明后,有多种计算机语言可以解决此问题。
def conflict(state , nextX):
nextY = len(state)
for i in range(nextY):
if abs(state[i] - nextX) in (0 , nextY - i ):
return True
return False
def queens(num = 8 , state = ()):
for pos in range(num):
if not conflict(state, pos):
if len(state) == num - 1:
yield (pos,)
else:
for result in queens(num , state + (pos,)):
yield (pos, ) + result
if __name__=='__main__':
print(len(list(queens(8))))
分享一种效率更高的方法
class Queen:
def __init__(self, q=8):
self.q = q
self.col = [1] * q # 矩阵列的列表,存储皇后所在列,若该列没有皇后,则相应置为1,反之则0
self.row = [0] * q # 矩阵行的列表,存放每行皇后所在的列位置,随着程序的执行,在不断的变化中,之间输出结果
self.pos_diag = [1] * (q*2+1) # 正对角线,i-j恒定,-7~0~7,并且b(i)+7统一到0~14
self.nag_diag = [1] * (q*2+1) # 负对角线,i+j恒定,0~14
self.count = 0
def getcount(self):
return self.count
def do_queen(self, i):
for j in range(0, self.q):
if self.col[j] == 1 and self.pos_diag[i-j+self.q-1] == 1 and self.nag_diag[i+j] == 1:
#若该行,正对角线,负对角线上都没有皇后,则放入i皇后
self.row[i] = j
self.col[j] = 0 #调整各个列表状态
self.pos_diag[i-j+self.q-1] = 0
self.nag_diag[i+j] = 0
if i < self.q-1:
self.do_queen(i+1) #可递增或递减
else:
# print(self.row)
self.count += 1
self.col[j] = 1 #恢复各个列表状态为之前的
self.pos_diag[i-j+self.q-1] = 1
self.nag_diag[i+j] = 1
if __name__ == '__main__':
f = Queen(8)
f.do_queen(0)
print(f.getcount())