劍指offer | 面試題12:矩陣中的路徑

轉載本文章請標明作者和出處
本文出自《愛喝純淨水的南榮牧歌》
本文題目和部分解題思路來源自《劍指offer》第二版

在這裏插入圖片描述

開始行動,你已經成功一半了,獻給正在奮鬥的我們

題目

請設計一個函數,用來判斷在一個矩陣中是否存在一條包含某字符串所有字符的路徑。路徑可以從矩陣中的任意一格開始,每一步可以在矩陣中向左、右、上、下移動一格。如果一條路徑經過了矩陣的某一格,那麼該路徑不能再次進入該格子。例如,在下面的3×4的矩陣中包含一條字符串“bfce”的路徑(路徑中的字母用加粗標出)。

[[“a”,“b”,“c”,“e”],
[“s”,“f”,“c”,“s”],
[“a”,“d”,“e”,“e”]]

但矩陣中不包含字符串“abfb”的路徑,因爲字符串的第一個字符b佔據了矩陣中的第一行第二個格子之後,路徑不能再次進入這個格子。

  • 示例 1:

    輸入:board = [[“A”,“B”,“C”,“E”],[“S”,“F”,“C”,“S”],[“A”,“D”,“E”,“E”]], word = “ABCCED”
    輸出:true

  • 示例 2:

    輸入:board = [[“a”,“b”],[“c”,“d”]], word = “abcd”
    輸出:false

  • 提示:

    1 <= board.length <= 200
    1 <= board[i].length <= 200

解題分析

這道題,只能使用暴力DFS+剪枝來做,就是依次的遍歷二位矩陣上面的所有節點,如果和給定的單詞第一個字母匹配,那麼我們就從這個節點開始,依次看他的上下左右的節點是不是和單詞的第二個字母匹配,一旦有一個不匹配,後面的就不用比較了,直接查看二位矩陣的下一個節點,如果一直匹配到了單詞的最後一個字母都相等的話,那就是已經有匹配的了,就可以終止遍歷二位矩陣,直接返回True;如果所有節點都查看完畢,還是沒有整體匹配的,就是整個二位矩陣都沒有匹配的,返回False;

值得一提的是,不允許重複的利用節點,我們可以在判斷完當前的節點等於單詞上的某個字母之後,把這個節點的值做一個修改,等到下面的節點遍歷返回結果的時候再給修改過來;

代碼

  • java實現

    class Solution {
        public boolean exist(char[][] board, String word) {
            if (Objects.isNull(board) || board.length == 0) {
                return false;
            }
            char[] chars = word.toCharArray();
            // 依次遍歷二維矩陣的所有節點
            for (int i = 0; i < board.length; i++) {
                for (int j = 0; j < board[0].length; j++) {
                    if (dfs(board,chars,i,j,0)) {
                        // 剪枝,已經找到,沒有必要再往下繼續
                        return true;
                    }
                }
            }
            return false;
        }
    
        public boolean dfs(char[][] board,char[] words,int line,int row,int index) {
            // 剪枝
            if (line >= board.length || row >= board[0].length || line < 0 || row < 0 || board[line][row] != words[index]) {
                return false;
            }
            // 單詞的最後一個字母也匹配上了,整體匹配完成
            if (index == words.length - 1) {
                return true;
            }
            // 已經匹配上的字母不能重複匹配,暫時修改節點的值
            char temp = board[line][row];
            board[line][row] = '/';
            boolean ifExist = dfs(board,words,line + 1,row,index + 1) || dfs(board,words,line - 1,row,index + 1)
                    || dfs(board,words,line,row + 1,index + 1) || dfs(board,words,line,row - 1,index + 1);
            // 還原節點上的值,以免影響下面的匹配
            board[line][row] = temp;
            // 返回這個節點開始的整體匹配結果 
            return ifExist;
        }
    }
    
  • python實現

    class Solution:
        def exist(self, board: List[List[str]], word: str) -> bool:
            if board is None or len(board) == 0:
                return False
            words = list(word)
            for i in range(len(board)):
                for j in range(len(board[0])):
                    if self.dfs(board, words, i, j, 0):
                        return True
            return False
    
        def dfs(self, board, words, i, j, index):
            if i >= len(board) or i < 0 or j >= len(board[0]) or j < 0 or board[i][j] != words[index]:
                return False
            if index == len(words) - 1:
                return True
            temp = board[i][j]
            board[i][j] = "1"
            if_exist = self.dfs(board, words, i, j - 1, index + 1) or self.dfs(board, words, i, j + 1, index + 1) or self.dfs(board, words, i + 1, j, index + 1) or self.dfs(board, words, i - 1, j, index + 1)
            board[i][j] = temp
            return if_exist
    

喜歡的朋友可以加我的個人微信,我們一起進步
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章