算法学习(十)

学习内容:

优先搜索算法:包括深度优先搜索和广度优先搜索;深度优先搜索(DFS):在搜索到一个新节点时,立即对该新节点进行遍历;因此遍历需要用先入后出的栈来实现,也可以通过与栈等价的递归来实现;广度优先搜索(BFS):一层层进行遍历,需要用先入先出的队列进行遍历。

学习产出:

回溯法:优先搜索特殊情况,常用于需要记录状态的深度优先搜索。步骤有修改当前节点状态—递归子节点—回改当前节点状态;
1.按引用传状态
2.所有状态修改在递归后完成
回溯法修改一般有两种情况:一是修改最后一位;二是修改访问标记

回溯法

LeetCode 79 单词搜索

给定一个二维网格和一个单词,找出该单词是否存在于网格中。

单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。

示例:

board =
[
  ['A','B','C','E'],
  ['S','F','C','S'],
  ['A','D','E','E']
]

给定 word = "ABCCED", 返回 true
给定 word = "SEE", 返回 true
给定 word = "ABCB", 返回 false

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/word-search
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
      
    

题解

修改访问标记,防止重复遍历,设置一个访问矩阵visited ,当已经访问过则设置为了True,回溯完后设置回来,当只有搜索成功时才返回True,如果backtracking无返回值,则返回False

代码(python)

class Solution:
    def exist(self, board: List[List[str]], word: str) -> bool:
        m,n = len(board),len(board[0])
        visited = [[False for col in range(n)] for row in range(m)] #生成遍历标记矩阵
        def backtracking(i, j, pos):
            visited[i][j] = True #修改当前节点状态
            if pos == len(word):
                return True
            #递归子节点
            if i != m - 1 and board[i + 1][j] == word[pos] and not visited[i + 1][j]:  #判断矩阵是否在边界或是已经遍历或词已经搜索出
                if backtracking(i + 1, j, pos + 1):
                    return True
            if i != 0 and board[i - 1][j] == word[pos] and not visited[i - 1][j]:
                if backtracking(i - 1, j, pos + 1):
                    return True
            if j != n - 1 and board[i][j + 1] == word[pos] and not visited[i][j + 1]:
                if backtracking(i, j + 1, pos + 1):
                    return True
            if j != 0 and board[i][j - 1] == word[pos] and not visited[i][j - 1]:
                if backtracking(i, j - 1, pos + 1):
                    return True
            visited[i][j] = False #修改回当前节点

        for i in range(len(board)):
            for j in range(len(board[0])):
                if board[i][j] == word[0]:
                    if (backtracking(i, j, 1)):
                        return True
        return False
    			

LeetCode 51 N 皇后

n 皇后问题 研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。

给你一个整数 n ,返回所有不同的 n 皇后问题 的解决方案。

每一种解法包含一个不同的 n 皇后问题 的棋子放置方案,该方案中 ‘Q’ 和 ‘.’ 分别代表了皇后和空位。

在这里插入图片描述

示例:

输入:n = 4
输出:[[".Q..","...Q","Q...","..Q."],["..Q.","Q...","...Q",".Q.."]]
解释:如上图所示,4 皇后问题存在两个不同的解法。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/n-queens
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。      
    

题解

类似于在矩阵中寻找字符串,也是通过修改状态矩阵来进行回溯,不同的是,对于每一行、列、斜建立访问数组,来记录是否存在皇后。分析发现,当满足条件的结果中每行或列有且仅有一个皇后。因此如果通过每一行来遍历插入皇后,则不需要对行建立访问数组。

代码(python)

class Solution:
    def solveNQueens(self, n: int) -> List[List[str]]:
        ans = [] #输出矩阵
        if n == 0 : return ans
        board = [['.' for col in range(n)] for row in range(n)] #记录状态矩阵
        colum = [False for row in range(n)] #列访问矩阵
        ldiag = [False for row in range(2 * n )] #左斜访问矩阵
        rdiag = [False for row in range(2 * n )] #右斜访问矩阵
        def backtracking(ans,board,colum,ldiag,rdiag,row,n): #回溯函数
            if row == n: #遍历结束
                b = [] #调整输出结果
                for i in range(n):
                    b.append(''.join(board[i]))
                ans.append(b)
                return
            for i in range(n):
                if colum[i]  or ldiag[n-row+i-1] or rdiag[row+i+1]: #检测是否被访问
                    continue
                board[row][i] = 'Q' #修改当前节点状态
                colum[i] = ldiag[n-row+i-1] = rdiag[row+i+1] = True   #修改当前访问节点状态
                backtracking(ans,board,colum,ldiag,rdiag,row+1,n) #递归子节点
                board[row][i] = '.' #回改当前节点状态
                colum[i] = ldiag[n-row+i-1] = rdiag[row+i+1] = False 	#回改当前访问节点状态
        backtracking(ans,board,colum,ldiag,rdiag,0,n)
        return ans



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值