矩阵路径
offer11将给出一个字符矩阵以及一个“路径”,试问矩阵中是否存在这样的一个路径。以下面的一个矩阵为例,它存在路径REALITY,但不存在路径FAKE:
回溯法
这里必然涉及简单的回溯法解题了。回溯法是一个类似枚举的搜索尝试过程,主要是在搜索尝试过程中寻找问题的解,当发现已不满足求解条件时,就“回溯”返回,尝试别的路径。它是一种选优搜索法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为“回溯点”。
这里借别人一张图:
分析
只有文字和伪代码可能还有所欠缺,我们再以REALITY和FAKE的搜索为例子:
REALITY的路径搜索
先遍历矩阵,找到位于第一排的R
→ 检查边界条件,R可以向三个方向搜索E,找到R下方的E
→ 标记R,此时E可以向左右下三个方向搜索A,找到E左边的A
→ 标记A,此时A可以向左上下三个方向搜索L,找到A左边的L
→ 标记L,此时L可以向上下两个方向搜索I,找到L下方的I
→ 标记I,此时I可以向右下两个方向搜索T,但是都没搜到→回到上一步的L
→ 在L的另外两个方向没有搜索到I,回到上一步的A→回到上一步的E→找到E右边的A
→ 以此类推,找到REALITY
(如果还没找到,还要对第三排的R进行相同的操作,实际上该例有2条路径)
我们可以注意到,在RE后的第一个分岔路口,我们先是向左深搜,直到走到尽头后再回头,然后再向右找到正解,这就是回溯。
FAKE的路径搜索
和REALITY的路径搜索类似,从第一排的F开始
→ 可以看到,F到A到K以后,因为没有E,所以向上回溯
→ 而A的周围只有一个K,F的周围只有一个A,回溯结束,return False
代码
这里仿照了一个大佬的代码。我第一次写得像bullsh*t,实在难登大雅之堂。思路和注释都写在代码上面了。
# offer11-solution
class Solution:
def MatrixPath(self, matrix, rows, cols, path): # 输入矩阵,行数,列数,路径
if not matrix or rows < 0 or cols < 0 or path == None:
return False
markmatrix = [0]*(rows*cols)
pathIndex = 0
for row in range(rows):
for col in range(cols): # 遍历找字符串中第一个字母
if self.MatrixPathCore(matrix, rows, cols, row, col, path, pathIndex, markmatrix):
return True
return False
def MatrixPathCore(self, matrix, rows, cols, row, col, path, pathIndex, markmatrix):
if pathIndex == len(path): # 最后一个index恰好能对应
return True
hasPath = False
# 不在边界条件上,且字符刚好能对应
if row >= 0 and row < rows and col >= 0 and col < cols and matrix[row*cols+col] == path[pathIndex] and not markmatrix[row * cols + col]:
pathIndex += 1 # index后移
markmatrix[row*cols+col] = True # 找到了,赋值为T,下面从四个方向进行回溯法
hasPath = self.MatrixPathCore(matrix, rows, cols, row+1, col, path, pathIndex, markmatrix) or \
self.MatrixPathCore(matrix, rows, cols, row-1, col, path, pathIndex, markmatrix) or \
self.MatrixPathCore(matrix, rows, cols, row, col+1, path, pathIndex, markmatrix) or \
self.MatrixPathCore(matrix, rows, cols, row, col-1, path, pathIndex, markmatrix)
if not hasPath:
pathIndex -= 1
markmatrix[row * cols + col] = False
return hasPath