https://leetcode-cn.com/problems/ju-zhen-zhong-de-lu-jing-lcof/
题目:请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一格开始,每一步可以在矩阵中向左、右、上、下移动一格。如果一条路径经过了矩阵的某一格,那么该路径不能再次进入该格子。
回溯 + 深度优先遍历
思路:
这是一个典型的回溯法的问题 参考leetcode官方讲解 https://leetcode-cn.com/problems/n-queens/solution/hui-su-suan-fa-xiang-jie-by-labuladong/
回溯法的核心就是递归调用的过程,在递归调用之前「做选择」,在递归调用之后「撤销选择」
其算法框架为
result = []
def backtrack(路径, 选择列表):
if 满足结束条件:
result.add(路径)
return
for 选择 in 选择列表:
做选择
backtrack(路径, 选择列表)
撤销选择
本题代码
时间复杂度,考虑搜索字符串长度为k,则每次搜索k个节点,每个节点搜索除过来节点的3个节点,则每次选定起始搜索点后,搜索时间复杂度3的k次幂。矩阵维度为m,n,则初始节点选择有mn种情况,时间复杂度O(mn*3^k)
空间复杂度使用额外矩阵记录节点是否被遍历O(m+n) 忽略递归深度
class Solution(object):
def dfs(self, board, flag, row, col, word):
if word == "":
return True
round_list = [(0, 1), (0, -1), (1, 0), (-1, 0)]
for i in range(0, len(round_list)):
if (row+round_list[i][0]) >= 0 and (row+round_list[i][0]) < len(board) and (col+round_list[i][1]) >= 0 and (col+round_list[i][1]) < len(board[0]) and not flag[row+round_list[i][0]][col+round_list[i][1]]:
flag[row+round_list[i][0]][col+round_list[i][1]] = True
if board[row+round_list[i][0]][col+round_list[i][1]] == word[0]:
if self.dfs(board, flag, row+round_list[i][0], col+round_list[i][1], word[1:]):
return True
flag[row+round_list[i][0]][col+round_list[i][1]] = False
return False
def exist(self, board, word):
"""
:type board: List[List[str]]
:type word: str
:rtype: bool
"""
if len(board) == 0:
if word == "":
return True
else:
return False
row = len(board)
col = len(board[0])
flag = [[False] * col for i in range(row)] # 这里不能写成flag = [[False]*n]*m,因为这么定义,其实是将一个n列的数组浅拷贝m次,当更改flag[i][j] 元素时,所有行的第i列元素都会遭到更改
for i in range(row):
for j in range(col):
if board[i][j] != word[0]:
continue
flag[i][j] = True
if self.dfs(board, flag, i, j, word[1:]):
return True
flag[i][j] = False
return False