1. 程式人生 > >【LeetCode】79-單詞搜索

【LeetCode】79-單詞搜索

int 結果 這一 || 還要 是否 進行 就是 符號

題目描述

給定一個二維網格和一個單詞,找出該單詞是否存在於網格中。

單詞必須按照字母順序,通過相鄰的單元格內的字母構成,其中 “相鄰” 單元格是那些水平相鄰或垂直相鄰的單元格。同一個單元格內的字母不允許被重復使用。

示例:

board =
[
  [‘A‘,‘B‘,‘C‘,‘E‘],
  [‘S‘,‘F‘,‘C‘,‘S‘],
  [‘A‘,‘D‘,‘E‘,‘E‘]
]

給定 word = "ABCCED", 返回 true.
給定 word = "SEE", 返回 true.
給定 word = "ABCB", 返回 false.

解題思路

回溯法

首先,需要一個輔助方法

boolean backtrack (int i, int j, int index, char[][] board, String word)

其中

  • char[][] boardString word就是題目給定的二維網格和單詞
  • int iint j是索引,表示從char[][] board中取出的元素
  • int index是索引,表示String word的字符

該回溯算法的輔助方法流程如下:

  • 如果當前字符串索引index == word.length(),表示有word.length()次匹配都成功了,直接返回true
  • 如果當前二維面板的索引超出有意義的範圍或當前考察的二維面板的值當前字符串的值不匹配,則返回false,結束這次搜索
  • 將當前二維面板的值取出來暫存,為後面回溯做準備
  • 用一個符號*表示這個元素已經使用過了,下次搜索就不能考慮它了(滿足題目不能重復的要求)
  • (遞歸地)搜索當前元素周圍的元素,看能否繼續匹配,直到得到一個結果
  • 將當前元素從*還原為以前的字符

最後,遍歷整個二維面板,對每一個匹配到word.charAt(0)的元素進行一次搜索,返回結果。

Java 實現

public boolean exist (char[][] board, String word) {
    for (int i = 0; i < board.length; i++) {
        for (int j = 0; j < board[0].length; j++) {
            if (board[i][j] == word.charAt(0)) {
                if (backtrack(i, j, 0, board, word)) {
                    return true;
                }
            }
        }
    }
    return false;
}

private boolean backtrack (int i, int j, int index, char[][] board, String word) {
    if (word.length() == index) return true;
    if (i < 0 || i >= board.length ||
            j < 0 || j >= board[0].length ||
            board[i][j] != word.charAt(index))
        return false;
    char c = board[i][j];
    board[i][j] = ‘*‘; // 標記,表示已使用過,不能再重復
    boolean ans;
    ans = backtrack(i + 1, j, index + 1, board, word)
            || backtrack(i - 1, j, index + 1, board, word)
            || backtrack(i, j + 1, index + 1, board, word)
            || backtrack(i, j - 1, index + 1, board, word);
    board[i][j] = c; // 用完之後還要換回來,方便別的元素使用
    return ans;
}

心得體會

這一題的搜索思想和深度優先搜索(DFS)有點類似,回溯算法體現在,搜索完成後,要把當前二維面板的元素置換回來,方便下次搜索中使用。

【LeetCode】79-單詞搜索