剑指 Offer 12. 矩阵中的路径
思路:
- 只要想到用dfs去解决,其实不是很难。
- 用下上右左的顺序去递归:
- 超出边界
- 字符不匹配
- 用一个巧妙的方法去避免flag的使用
代码
class Solution:
def exist(self, board: List[List[str]], word: str) -> bool:
def dfs(i, j, k):
if i<0 or j<0 or i>len(board)-1 or j>len(board[0])-1: return False
if board[i][j] != word[k]: return False
if k == len(word)-1: return True
tmp, board[i][j] = 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] = tmp
return res
for i in range(len(board)):
for j in range(len(board[0])):
res = dfs(i, j, 0)
if res: return True
return False
收获
其实只要想到dfs的递归方法,就能一点点剥开去解决。最主要学到的是用res来保存递归的结果,然后在res前后用暂时空白化的方式去代替flag的作用。很巧妙很简洁。
剑指 Offer 13. 机器人的运动范围
思路:
跟上题类似,用dfs解决。
但是有很大的改进空间:
- sum在i<100时有特例,
- si += 1 if i%10 else s-8
- 用set判断值是否在其中的速度比list要快很多,因为set使用hash做的,查找操作的时间是 O ( 1 ) O(1) O(1)详情见这里
代码:
class Solution:
def movingCount(self, m: int, n: int, k: int) -> int:
def sum(i):
a0, a1 = i%10, i//10
s = a0+a1
return s
def dfs(i, j):
if i < 0 or j<0 or i>=m or j>= n or (i,j) in visited or sum(i)+sum(j)>k: return 0
visited.append((i,j))
return 1+dfs(i+1, j)+dfs(i,j+1)
visited = []
return dfs(0, 0)
改进:
class Solution:
def movingCount(self, m: int, n: int, k: int) -> int:
def dfs(i, j, si, sj):
if i >= m or j >= n or k < si + sj or (i, j) in visited: return 0
visited.add((i,j))
return 1 + dfs(i + 1, j, si + 1 if (i + 1) % 10 else si - 8, sj) + dfs(i, j + 1, si, sj + 1 if (j + 1) % 10 else sj - 8)
visited = set()
return dfs(0, 0, 0, 0)