• 【python刷题】回溯算法(深度优先搜索DFS)


    回溯算法框架:

    result = []
    def backtrack(路径, 选择列表):
        if 满足结束条件:
            result.add(路径)
            return
    
        for 选择 in 选择列表:
            做选择
            backtrack(路径, 选择列表)
            撤销选择
    

    多叉树的遍历框架

    def traverse(TreeNode root):
        for child in root.children:
            #前向遍历需要的操作
            traverse(dhild)
            #后向遍历需要的操作
    

    全排列问题

    def permutation(nums):
        def backtrack(nums, tmp):
            # 如果tmp中满了,则排列完成,将临时数组加入到res中
            if len(tmp) == len(nums):
                res.append(tmp[:])
                return
            for i in range(len(nums)):
                # 选择一个数加入到tmp中,如果tmp中已存在,则继续
                if nums[i] in tmp:
                    continue
                tmp.append(nums[i])
                # 递归选择
                backtrack(nums, tmp)
                # 将最后一个数删除
                tmp.pop()
        res = []
        backtrack(nums, [])
        return res
    res = permutation([1, 2, 3])
    print(res)
    

    结果:
    [[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]]

    子集问题

    def subset(nums):
        def trackback(nums, k, tmp):
            res.append(tmp[:])
            for i in range(k, len(nums)):
                tmp.append(nums[i])
                trackback(nums, i+1, tmp)
                tmp.pop()
        res = []
        trackback(nums, 0, [])
        return res
    res = subset([1, 2, 3])
    print(res)
    

    结果:
    [[], [1], [1, 2], [1, 2, 3], [1, 3], [2], [2, 3], [3]]

    八皇后

    from pprint import pprint
    
    class NQueue:
        def __init__(self, n):
            self.board = [['.' for _ in range(n)] for _ in range(n)]
            self.count = 0
            self.trackback(self.board, 0)
    
        def trackback(self, board, row):
            # 从第0行开始放置
            if row == len(board):
                print(board)
                self.count += 1
                return
            n = len(board)
            for col in range(n):
                if not self.isValid(board, row, col):
                    continue
                board[row][col] = 'Q'
                self.trackback(board, row + 1)
                board[row][col] = '.'
    
        # 是否可以在board[row][col]放置皇后
        def isValid(self, board ,row, col):
            n = len(board)
            # 如果第rol列上存在Q,返回False
            for i in range(n):
                if board[i][col] == 'Q':
                    return False
            # 检查右上方是否冲突
            i,j = row-1, col+1
            while i >=0 and j < n:
                if board[i][j] == 'Q':
                    return False
                i -= 1
                j += 1
            # 检查左上方是否冲突
            i,j = row-1, col-1
            while i >= 0 and j >= 0:
                if board[i][j] == 'Q':
                    return False
                i -= 1
                j -= 1
            return True
    
    
    nQueen = NQueue(8)
    pprint(nQueen.count)
    

    结果:
    92

    组合

    输入两个数字 n, k,算法输出 [1..n] 中 k 个数字的所有组合
    比如输入 n = 4, k = 2,输出如下结果,顺序无所谓,但是不能包含重复(按照组合的定义,[1,2] 和 [2,1] 也算重复):
    [
    [1,2],
    [1,3],
    [1,4],
    [2,3],
    [2,4],
    [3,4]
    ]
    k 限制了树的高度,n 限制了树的宽度

    def combine(n, k):
        nums = [i for i in range(1, n+1)]
        def trackback(nums, t, k, tmp):
            if len(tmp) == k:
                res.append(tmp[:])
                return
            for i in range(t, len(nums)):
                tmp.append(nums[i])
                trackback(nums, i+1, k, tmp)
                tmp.pop()
        res = []
        trackback(nums, 0, k, [])
        return res
    res = combine(4, 2)
    print(res)
    

    结果:
    [[1, 2], [1, 3], [1, 4], [2, 3], [2, 4], [3, 4]]

    解数独

    from pprint import pprint
    
    board = [[0 for _ in range(9)] for _ in range(9)]
    
    def solveSudoku():
        global board
        # 从棋盘上的0,0位置开始
        trackback(board, 0, 0)
    
    def trackback(board, row, col):
        m, n = 9, 9
        # 穷举到某行的最后一列,再从下一行开始
        if col == n:
            return trackback(board, row+1, 0)
        # 如果穷举到最后一行了, 打印棋盘,并返回True
        if row == m:
            pprint(board)
            return True
        # 每次从(row,col)位置开始,穷举到(m,n)位置
        for i in range(row, m):
            for j in range(col, n):
                # 如果当前位置是预设了值的,就跳过,继续下一列
                if board[i][j] != 0:
                    return trackback(board, i, j+1)
                # 判断穷举出来的值是否符合规则
                for k in range(1,10):
                    # 如果不是有效的,则继续
                    if not isValid(board, i, j, k):
                        continue
                        # 否则当前位置变为k
                    board[i][j] = k
                    # 如果下一列穷举返回True,返回True
                    if trackback(board, i, j+1):
                        return True
                    # 将i,j出还原为0,继续穷举
                    board[i][j] = 0
                return False
        return False
    
    def isValid(board, i, j, k):
        # 判断该值所在行列是否有重复
        for m in range(9):
            if board[i][m] == k:
                return False
            if board[m][j] == k:
                return False
            # 3×3小格中是否有重复
            if board[(i//3)*3+m//3][(j//3)*3+m%3] == k:
                return False
        return True
    
    solveSudoku()
    

    结果:
    [[1, 2, 3, 4, 5, 6, 7, 8, 9],
    [4, 5, 6, 7, 8, 9, 1, 2, 3],
    [7, 8, 9, 1, 2, 3, 4, 5, 6],
    [2, 1, 4, 3, 6, 5, 8, 9, 7],
    [3, 6, 5, 8, 9, 7, 2, 1, 4],
    [8, 9, 7, 2, 1, 4, 3, 6, 5],
    [5, 3, 1, 6, 4, 2, 9, 7, 8],
    [6, 4, 2, 9, 7, 8, 5, 3, 1],
    [9, 7, 8, 5, 3, 1, 6, 4, 2]]

    leetcode 22. 括号生成

    数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。
    输入:n = 3
    输出:["((()))","(()())","(())()","()(())","()()()"]
    输入:n = 1
    输出:["()"]

    from pprint import pprint
    
    
    def generateParenthesis(n):
        res = []
        trackback(n, n, [], res)
        return res
    
    # left,right用于左括号和右括号的个数
    def trackback(left, right, tmp, res):
        if right < left:
            return
        if left < 0 or right < 0:
            return
        if left == 0 and right == 0:
            res.append(tmp[:])
            return
        tmp.append('(')
        trackback(left-1, right, tmp, res)
        tmp.pop()
    
        tmp.append(')')
        trackback(left, right-1, tmp, res)
        tmp.pop()
    
    res = generateParenthesis(3)
    pprint(res)from pprint import pprint
    
    
    def generateParenthesis(n):
        res = []
        trackback(n, n, [], res)
        return res
    
    # left,right用于左括号和右括号的个数
    def trackback(left, right, tmp, res):
        if right < left:
            return
        if left < 0 or right < 0:
            return
        if left == 0 and right == 0:
            res.append(tmp[:])
            return
        tmp.append('(')
        trackback(left-1, right, tmp, res)
        tmp.pop()
    
        tmp.append(')')
        trackback(left, right-1, tmp, res)
        tmp.pop()
    
    res = generateParenthesis(3)
    pprint(res)
    

    寻找二维字母矩阵中是否存在某单词

    # -*- coding:utf-8 -*-
    class Solution:
        def hasPath(self, matrix, path):
            # write code here
            def helper(matrix,path,i,j):
                if len(path) == 0:
                    return True
                haspath = False
                if 0<= i < len(matrix) and 0<= j< len(matrix[0]):
                    if path[0] == matrix[i][j]:
                        matrix[i][j] = 0
                        haspath = helper(matrix,path[1:],i+1,j) or 
                                  helper(matrix, path[1:], i, j+1) or 
                                  helper(matrix, path[1:], i-1, j) or 
                                  helper(matrix, path[1:], i, j-1)
                        matrix[i][j] = path[0]
                return haspath
            m,n = len(matrix),len(matrix[0])
            for i in range(m):
                for j in range(n):
                    if helper(matrix,path,i,j):
                        return True
            return False
    
    s = Solution()
    matrix = [
        ['h','a','l','m','n'],
        ['c','a','m','q','y'],
        ['w','e','d','e','q'],
        ['z','e','t','o','i'],
    ]
    path = 'almdeoi'
    print(s.hasPath(matrix,path=path))
    
  • 相关阅读:
    同一个硬盘安装win10+ubuntu双系统
    Bundle
    layout_weight属性
    Java反射机制
    Android——Widget实现
    Android——悬浮窗+侧边弹框+淡入淡出+背景shape+SeekBar调节手机亮度
    Android权限总结
    Android——窗口层控制WindowManager.LayoutParams.type
    Android——getSystemService
    Eclipse UML插件——AmaterasUML
  • 原文地址:https://www.cnblogs.com/xiximayou/p/14361950.html
Copyright © 2020-2023  润新知