剑指Offer刷题笔记——矩阵中的路径

请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向上,向下移动一个格子。如果一条路径经过了矩阵中的某一个格子,则该路径不能再进入该格子。 例如在下面的3x4的矩阵中包含一条字符串"bcced"的路径(路径中的字母用斜体表示)。但是矩阵中不包含"abcb"路径,因为字符串的第一个字符b占据了矩阵中的第一行第二个格子之后,路径不能再次进入这个格子。

剑指Offer刷题笔记——矩阵中的路径_第1张图片

这是一个可以用回溯法解决的典型问题。
首先,遍历这个矩阵,我们很容易就能找到与字符串str中第一个字符相同的矩阵元素ch。然后遍历ch的上下左右四个字符,如果有和字符串str中下一个字符相同的,就把那个字符当作下一个字符(下一次遍历的起点),如果没有,就需要回退到上一个字符,然后重新遍历。为了避免路径重叠,需要一个辅助矩阵来记录路径情况。
当矩阵坐标为(row,col)的格子和路径字符串中下标为pathLength的字符一样时,从4个相邻的格子(row,col-1)、(row-1,col)、(row,col+1)以及(row+1,col)中去定位路径字符串中下标为pathLength+1的字符。
如果4个相邻的格子都没有匹配字符串中下标为pathLength+1的字符,表明当前路径字符串中下标为pathLength的字符在矩阵中的定位不正确,我们需要回到前一个字符串(pathLength-1),然后重新定位。
一直重复这个过程,直到路径字符串上所有字符都在矩阵中找到格式的位置(此时str[pathLength] == '\0')。

# -*- coding:utf-8 -*-
# Python Solution
# 构造board二维数组来存储原有一维数组# 利用dict列表来存储已经经过的路径
# 利用word来存储,还需遍历的字符
# 构造4个方向的递归,设置截至条件 word == ''
class Solution:    
    # word是需要的找路径的字符串
    # col列 row行
    def hasPath(self, board, row, col, word):            
        self.col, self.row = col, row 
        # 把board变成二维的数组           
        board = [list(board[col * i:col * i + col]) for i in range(row)]
        # 遍历二位数组,把每一个位置作为起点            
        for i in range(row):                
            for j in range(col):
                # 这个元素和被寻找的字符串最前的相同,就继续往下找                    
                if board[i][j] == word[0]:                        
                    self.b = False                        
                    self.search(board, word[1:], [(i, j)], i, j)
                    if self.b:                            
                        return True            
        return False    
    # dict保存到是已经走过的元素位置
    # 此时的word已经原来的第一个元素拿出去了
    def search(self, board, word, dict, i, j):    
        # 只有完全找到一条路径的时候才会修改self.b的是数值        
        if word == "":                
            self.b = True                
            return     
        # 以i,j为起点上下左右遍历       
        # 边界条件&没有遍历过&数值相等&没找到路径
        if j != 0 and (i, j - 1) not in dict and board[i][j - 1] == word[0] and self.b:
            self.search(board, word[1:], dict + [(i, j - 1)], i, j - 1)            
        if i != 0 and (i - 1, j) not in dict and board[i - 1][j] == word[0] and self.b:
            self.search(board, word[1:], dict + [(i - 1, j)], i - 1, j)            
        if j != self.col - 1 and (i, j + 1) not in dict and board[i][j + 1] == word[0]and self.b:
            self.search(board, word[1:], dict + [(i, j + 1)], i, j + 1)            
        if i != self.row - 1 and (i + 1, j) not in dict and board[i + 1][j] == word[0]and self.b: 
            self.search(board, word[1:], dict + [(i + 1, j)], i + 1, j)

 tuple  ():元组的元素不能改

 set  {} :集合是无序不重复的元素集合。  (空元素是set(),不能用{},{}是声明一个空的字典)

为了提高性能,在判断新的路径之前,应该考虑当前是否找到了路径,如果找到了就应该不再寻找。

 

你可能感兴趣的:(剑指Offer刷题笔记——矩阵中的路径)