LeetCode筆記——79單詞搜尋
題目:
給定一個二維網格和一個單詞,找出該單詞是否存在於網格中。
單詞必須按照字母順序,通過相鄰的單元格內的字母構成,其中“相鄰”單元格是那些水平相鄰或垂直相鄰的單元格。同一個單元格內的字母不允許被重複使用。
示例:
board = [ ['A','B','C','E'], ['S','F','C','S'], ['A','D','E','E'] ] 給定 word = "ABCCED", 返回 true. 給定 word = "SEE", 返回 true. 給定 word = "ABCB", 返回 false.
思路:直接看了大神們的思路和程式碼,原文連結:https://blog.csdn.net/DERRANTCM/article/details/47248121
整個程式碼使用了回溯的思想,就是迭代加上迴圈。需要的資料結構包括一個記錄是否訪問過的陣列,一個記錄檢查到給定字元的哪個位置的陣列。首先遍歷陣列中的每一個元素,對於一個元素檢查該元素是否合法,即行列號是否合法,是否被訪問過,是否與對應word中的值相等,若這一切條件均滿足,則遞迴呼叫函式檢查上下左右的位置;如果搜尋的位置等於字串的長度,說明已經找到找到匹配的了, 如果沒有找到路徑(hasPath=false)就回溯。
程式碼:
class Solution {
public boolean exist(char[][] board, String word) { // 【注意我們假定輸入的引數都是合法】
// 訪問標記矩陣,初始值預設會設定為false
boolean[][] visited = new boolean[board.length][board[0].length];
// 以每一個位置為起點進行搜尋,找到一個路徑就停止
for (int i = 0; i < board.length; i++) {
for (int j = 0; j < board[0].length; j++) {
if (search(board, visited, i, j, word, new int[]{0})) {
return true;
}
}
}
return false;
}
/**
* @param board 字元矩陣
* @param visited 訪問標記矩陣
* @param row 訪問的行號
* @param col 訪問的列號
* @param word 匹配的字串
* @param idx 匹配的位置,取陣列是更新後的值可以被其它引用所見
* @return
*/
private boolean search(char[][] board, boolean[][] visited, int row, int col, String word, int[] idx) {
// 如果搜尋的位置等於字串的長度,說明已經找到找到匹配的了
if (idx[0] == word.length()) {
return true;
}
boolean hasPath = false;
// 當前位置合法
if (check(board, visited, row, col, word, idx[0])) {
// 標記位置被訪問過
visited[row][col] = true;
idx[0]++;
// 對上,右,下,左四個方向進行搜尋
hasPath = search(board, visited, row - 1, col, word, idx ) // 上
|| search(board, visited, row, col + 1, word, idx) // 右
|| search(board, visited, row + 1, col, word, idx) // 下
|| search(board, visited, row, col - 1, word, idx); // 左
// 如果沒有找到路徑就回溯
if (!hasPath) {
visited[row][col] = false;
idx[0]--;
}
}
return hasPath;
}
/**
* 判定訪問的位置是否合法
*
* @param board 字元矩陣
* @param visited 訪問標記矩陣
* @param row 訪問的行號
* @param col 訪問的列號
* @param word 匹配的字串
* @param idx 匹配的位置
* @return
*/
public boolean check(char[][] board, boolean[][] visited, int row, int col, String word, int idx) {
return row >= 0 && row < board.length // 行號合法
&& col >= 0 && col < board[0].length // 列號合法
&& !visited[row][col] // 沒有被訪問過
&& board[row][col] == word.charAt(idx);
// 字元相等
}
}
執行最快的的程式碼:
思路和上面的相同。
class Solution { int m; int n; public boolean exist(char[][] board, String word) { if (null == board || word == null || word.isEmpty()) { return false; } boolean[][] used = new boolean[board.length][board[0].length]; m = board.length; n = board[0].length; char[] charArray = word.toCharArray(); for(int i=0; i<m; i++) { for(int j=0; j<n;j++) { if (exist(board, used, charArray, i, j, 0)) { return true; } } } return false; } private boolean exist(char[][] board, boolean[][] mem, char[] charArray, int i, int j, int index) { if (index == charArray.length) { return true; } if (i >= m || i < 0) { return false; } if (j >= n || j < 0) { return false; } if (mem[i][j] || board[i][j] != charArray[index]) { return false; } mem[i][j] = true; // up -> right -> down -> left boolean found = exist(board, mem, charArray, i - 1, j, index + 1) || exist(board, mem, charArray, i, j + 1, index + 1) || exist(board, mem, charArray, i + 1, j, index + 1) || exist(board, mem, charArray, i, j - 1, index + 1); // recover if (!found) mem[i][j] = false; return found; } }