题目12 矩阵中的路径
给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中,返回 true ;否则,返回 false 。
单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。
例如,在下面的 3×4 的矩阵中包含单词 "ABCCED"(单词中的字母已标出)。
思路
矩阵里面搜索的题想到用dfs,但是如何记录已经搜索过的字母的?我之前的思路是使用一个visited矩阵来标记每一次搜索中使用过的字母,但是想想好像很复杂。后来看了题解真是豁然开朗,利用dfs+剪枝即可,直接贴代码吧。
代码
官方题解中直接四个dfs还可以优化成使用for循环判断dfs进入条件是否满足,如下所示:
dirt = [-1,0,1,0,-1]
for i in range(4):
xx = x+dirt[i]
yy = y+dirt[i+1]
if xx>=0 and yy>=0 and xx<len(dp) and yy<len(dp[0]):
res = res or dfs(xx,yy,k+1)
官方题解
class Solution:
def exist(self, board: List[List[str]], word: str) -> bool:
def dfs(i, j, k):
if not 0 <= i < len(board) or not 0 <= j < len(board[0]) or board[i][j] != word[k]: return False
if k == len(word) - 1: return True
board[i][j] = ''
res = dfs(i + 1, j, k + 1) or dfs(i - 1, j, k + 1) or dfs(i, j + 1, k + 1) or dfs(i, j - 1, k + 1)
board[i][j] = word[k]
return res
for i in range(len(board)):
for j in range(len(board[0])):
if dfs(i, j, 0): return True
return False
题目13 机器人运动范围
地上有一个m行n列的方格,从坐标 [0,0] 到坐标 [m-1,n-1] 。一个机器人从坐标 [0, 0] 的格子开始移动,它每次可以向左、右、上、下移动一格(不能移动到方格外),也不能进入行坐标和列坐标的数位之和大于k的格子。例如,当k为18时,机器人能够进入方格 [35, 37] ,因为3+5+3+7=18。但它不能进入方格 [35, 38],因为3+5+3+8=19。请问该机器人能够到达多少个格子?
思路
这题刚开始觉得是动态规划,先判断出哪些格子可以被走到,再将那些上下左右四个方向的格子均为False的True格子给去掉即可。这样做的问题是有些格子它的临近格子其实也不能走到,但是由于还没遍历到它,因此不能使用该方法,如图所示,打叉的格子都是实际上不能被到达的。
后面观察发现其实只需要从左上角开始进行dfs,类似于得到岛屿的最大面积即可。
代码
class Solution:
def movingCount(self, m: int, n: int, k: int) -> int:
#感觉是个动态规划的题
dp = [[0]*n for _ in range(m)]
self.count = 0
#将数字的各位相加
def sum(x):
s = str(x)
res = 0
for i in range(len(s)):
res+=int(s[i])
return res
dirt = [-1,0,1,0,-1]
#岛屿面积
def dfs(x, y, dp):
if dp[x][y]==0:
return
else:
dp[x][y]=0
self.count+=1
for i in range(4):
xx = x+dirt[i]
yy = y+dirt[i+1]
if xx>=0 and yy>=0 and xx<len(dp) and yy<len(dp[0]):
dfs(xx,yy,dp)
for i in range(m):
for j in range(n):
if sum(i)+sum(j)<=k:
dp[i][j] = 1
dfs(0,0,dp)
return self.count