力扣 - 劍指 Offer 12. 矩陣中的路徑

linzeliang發表於2021-11-21

題目

劍指 Offer 12. 矩陣中的路徑

思路1(回溯、DFS)

  • 這題可以使用回溯+遞迴來解決,思路如下:
    1. 將二維陣列的每一個元素都作為起點進行回溯查詢
    2. 每次查詢的時候,都有四個方向,但是上一個方向不能再次被遍歷,因此需要將遍歷過的位置進行做標記,遞迴返回的時候再還原
    3. 遞迴過程中要判斷一些條件:越界直接返回false、當前字元和word中的不匹配也直接返回false
    4. 何時為匹配成功呢?只要能匹配到word的最後一個字元,即curIndex == cs.length-1(curIndex為每次搜尋的深度,不過是從0開始的,就是在word中的位置;cs.length-1為最後一個字元的索引位置),因此後面剩下的就不用查詢了

程式碼

class Solution {
    public boolean exist(char[][] board, String word) {
        char[] cs = word.toCharArray();
        
        // 遍歷整個二維陣列,即將每個字元作為第一個字元進行嘗試
        for (int i = 0; i < board.length; i++) {
            for (int j = 0; j < board[0].length; j++) {
                // 只要有一條符合條件,則返回true
                if (dfs(board, cs, i, j, 0)) {
                    return true;
                }
            }
        }

        // 沒找到
        return false;
    }

    public boolean dfs(char[][] board, char[] cs, int i, int j, int curIndex) {
        // 超過二維陣列邊界就返回false
        // 字元不匹配也直接結束遞迴
        if (i < 0 || i >= board.length || j < 0 || j >= board[0].length || board[i][j] != cs[curIndex]) {
            return false;
        }

        // 如果以及全部匹配到了,就直接返回true,而不用繼續匹配剩下的啦
        if (curIndex == cs.length - 1) {
            return true;
        }

        // 能遞迴到這裡,說明當前cs中curIndex索引對應的字元和boards是匹配的
        // 因此我們需要吧遍歷過的字元設定為空白,防止再次遍歷
        board[i][j] = '\0';
        boolean res = dfs(board, cs, i + 1, j, curIndex + 1) ||
                      dfs(board, cs, i - 1, j, curIndex + 1) ||
                      dfs(board, cs, i, j + 1, curIndex + 1) ||
                      dfs(board, cs, i, j - 1, curIndex + 1);
        // 回溯的時候要把原來設定為空白字元的還原
        board[i][j] = cs[curIndex];

        // 只要出現true,就一路返回
        return res;
    }
}

複雜度分析

  • 時間複雜度:\(O(MN·3^K)\),二維陣列共有M·N個起點;然後對於每個起點來說,每步都有三個方向可以選擇(不包括上一個方向),最長要走的步數就是word的長度K,因此複雜度為\(3^K\)
  • 空間複雜度:\(O(K)\),遞迴深度最深也就是word的長度

相關文章