递归
案例
- 斐波那契数列,阶乘
- 归并排序,快排
- 二分查找
- 树的遍历:先根、中根、后根遍历
- 图的遍历:宽度优先、广度优先
- 动态规划
- 分治算法
- 汉诺塔问题
- 回溯法
例1:汉诺塔问题
汉诺塔问题里有三个柱子ABC,原始的柱子A上已经按上小下大的顺序穿了
个盘子。我们要把所有的盘子从A移动到C,B用于辅助移动,移动盘子的规则:
- 一次只能移动一个柱子最上方的一个盘到另一个柱子上
- 不能将大盘压在小盘上
思路:移动中最关键的一步是,将柱A最底下的大盘移动到C,前提是前 个盘子已经顺序摆在了柱B上!接下来就是一个子问题:将 个盘从柱B移动到柱C。
def TowersOfHanoi(numberOfDisks, startPeg=1, endPeg=3):
if numberOfDisks > 0:
TowersOfHanoi(numberOfDisks-1, startPeg, 6-startPeg-endPeg) # 1+2+3=6
print("Move disk %d from peg %d to peg %d" % (numberOfDisks, startPeg, endPeg))
TowersOfHanoi(numberOfDisks-1, 6-startPeg-endPeg, endPeg)
TowersOfHanoi(numberOfDisks=4)
'''
Move disk 1 from peg 1 to peg 2
Move disk 2 from peg 1 to peg 3
Move disk 1 from peg 2 to peg 3
Move disk 3 from peg 1 to peg 2
Move disk 1 from peg 3 to peg 1
Move disk 2 from peg 3 to peg 2
Move disk 1 from peg 1 to peg 2
Move disk 4 from peg 1 to peg 3
Move disk 1 from peg 2 to peg 3
Move disk 2 from peg 2 to peg 1
Move disk 1 from peg 3 to peg 1
Move disk 3 from peg 2 to peg 3
Move disk 1 from peg 1 to peg 2
Move disk 2 from peg 1 to peg 3
Move disk 1 from peg 2 to peg 3
'''
上述递归算法的时间复杂度: 所以
例2:检验数组是否顺序排列
def isSorted(A):
if len(A) == 1:
return True
return A[0] <= A[1] and isSorted(A[1:])
回溯法
backtracking, 回溯法是递归应用的场景之一,基本上可以视为利用分治思想的穷举法。
案例
- Binary Strings: generating all binary strings
- The Knapsack Problem
- Generalized Strings
- 哈密顿环
- 图着色问题
例1:Bit Strings
def bitStrings(n):
if n == 0:
return []
if n == 1:
return ["0", "1"]
return [digit+bitString for digit in bitStrings(1) for bitString in bitStrings(n-1)]
bitStrings(4)
'''
['0000',
'0001',
'0010',
'0011',
'0100',
'0101',
'0110',
'0111',
'1000',
'1001',
'1010',
'1011',
'1100',
'1101',
'1110',
'1111']
'''
例2:最大连通域面积
def getval(A, i, j, L, H):
if i < 0 or i >= L or j < 0 or j >= H:
return 0
else:
return A[i][j]
direction=[[ -1,0],[-1, -1],[0,- 1],[1,- 1],[1 ,0],[1, 1],[0,1],[-1, 1]]
def findMaxBlock(A, r, c, L, H, size):
global maxsize
if r >= L or c >= H:
return
cntarr[r][c] = 1
size += 1
if size > maxsize:
maxsize = size
for d in direction:
newi = r + d[0]
newj = c + d[1]
var = getval (A, newi, newj, L, H)
if var > 0 and cntarr[newi][newj]==0:
findMaxBlock(A, newi, newj, L, H, size)
cntarr[r][c] = 0
def getMaxOnes(A, rmax, colmax):
for i in range(0,rmax):
for j in range(0,colmax):
if (A[i][j] == 1):
findMaxBlock(A, i, j, rmax, colmax, 0)
return maxsize
zarr=[[1,1,0,0,0],[0,1,1,0,1],[0,0,0,0,1],[1,0,1,0,1],[0,1,0,1,1 ]]
'''
11000
01101
00001
10101
01011
'''
rmax = 5
colmax = 5
maxsize = 0
cntarr=[colmax*[0] for i in range(rmax)]
print(getMaxOnes(zarr, rmax, colmax)) # 8