Leetcode 79. Word Search
題目:
The word can be constructed from letters of sequentially adjacent cell, where "adjacent" cells are those horizontally or vertically neighboring. The same letter cell may not be used more than once. Example: board = [['A','B','C','E'],['S','F','C','S'],['A','D','E','E']] Given word = "ABCCED", return true. Given word = "SEE", return true. Given word = "ABCB", return false.
這是一道搜尋題,用backtracking做,問題就是怎樣設計這個回溯過程。
我們需要的就是在這個二維數組裡面一個個尋找每個字元,所以dfs的終止條件是當我們把每個字元全部搜尋了,也就是index==word.length。因為每個字元只能使用一次所以我們還需要一個visited陣列來記錄當前元素是否被訪問過,如果我們找到了和當前搜尋的字元相匹配的元素,我們就要上下左右搜尋四個方向。
這麼看來思路還是很清晰的,但是我在做這一題時被幾點困擾:1.我們需要遍歷二維陣列,但同時我們又需要移動移動被搜尋字串的index,一開始我是把遍歷二維陣列和移動字串的index寫在了同一個dfs的recursion裡面然後接下去我就沒辦法寫了,看了discuss之後才知道應該把遍歷二維陣列寫在主函式裡面,讓它來呼叫dfs。2.選擇下一個可以走的adjacent,我一開始還在想需不需要用一個list來儲存每一步可以走的adjacent,這樣的話就太麻煩了,還需要分情況討論,但其實是沒有必要的。我們把這些判斷都加在recursion的終止條件裡面就好了。
程式碼如下:
class Solution { public boolean exist(char[][] board, String word) { int m = board.length, n = board[0].length; boolean[][] visited = new boolean[m][n]; for (int i = 0; i < board.length; i ++) { for (int j = 0; j < board[0].length; j ++) { if (word.charAt(0) == board[i][j] && dfs(board, word, visited, 0, i, j)) return true; } } return false; } public boolean dfs(char[][] board, String word, boolean[][] visited, int index, int row, int col) { if (index == word.length()) return true; if (row == board.length || row < 0 || col == board[0].length || col < 0 || visited[row][col] || word.charAt(index) != board[row][col])return false; visited[row][col] = true; if (dfs(board, word, visited, index+1, row+1, col) || dfs(board, word, visited, index+1, row, col+1) || dfs(board, word, visited, index+1, row-1, col) || dfs(board, word, visited, index+1, row, col-1)) return true; visited[row][col] = false; return false; } }