python 数据结构与算法——递归与回溯

递归

案例

  • 斐波那契数列,阶乘
  • 归并排序,快排
  • 二分查找
  • 树的遍历:先根、中根、后根遍历
  • 图的遍历:宽度优先、广度优先
  • 动态规划
  • 分治算法
  • 汉诺塔问题
  • 回溯法

例1:汉诺塔问题

在这里插入图片描述
汉诺塔问题里有三个柱子ABC,原始的柱子A上已经按上小下大的顺序穿了 N N 个盘子。我们要把所有的盘子从A移动到C,B用于辅助移动,移动盘子的规则:

  • 一次只能移动一个柱子最上方的一个盘到另一个柱子上
  • 不能将大盘压在小盘上

思路:移动中最关键的一步是,将柱A最底下的大盘移动到C,前提是前 N 1 N-1 个盘子已经顺序摆在了柱B上!接下来就是一个子问题:将 N 1 N-1 个盘从柱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
'''

上述递归算法的时间复杂度: T ( n ) = 2 T ( n 1 ) + 1 T(n) = 2T(n-1)+1 所以 T ( n ) = O ( 2 n ) T(n)=O(2^n)

例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
发布了274 篇原创文章 · 获赞 446 · 访问量 42万+

猜你喜欢

转载自blog.csdn.net/itnerd/article/details/103859187