Word Search
Given a 2D board and a word, find if the word exists in the grid.
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.
For example,
Given board =
[
["ABCE"],
["SFCS"],
["ADEE"]
]
word = "ABCCED", -> returns true,
word = "SEE", -> returns true,
word = "ABCB", -> returns false.
Solution1:
這個題目基本上就是DFS嘍。然后注意一下遞歸回溯的問題。我們可以建設一個boolean的數組來記錄訪問過的值。在return false之前,我們應該把之前置
過的標記位置回來. 時間復雜度: http://www1.mitbbs.ca/article_t1/JobHunting/32524193_32524299_2.html
time 復雜度是m*n*4^(k-1). 也就是m*n*4^k.
m X n is board size, k is word size.
recuision最深是k層,recursive部分空間復雜度應該是O(k) + O(m*n)(visit array)

1 package Algorithms.dfs; 2 3 public class Exist { 4 public boolean exist(char[][] board, String word) { 5 if (board == null || word == null 6 || board.length == 0 || board[0].length == 0) { 7 return false; 8 } 9 10 int rows = board.length; 11 int cols = board[0].length; 12 13 boolean[][] visit = new boolean[rows][cols]; 14 15 // i means the index. 16 for (int i = 0; i < rows; i++) { 17 for (int j = 0; j < cols; j++) { 18 // dfs all the characters in the matrix 19 if (dfs(board, i, j, word, 0, visit)) { 20 return true; 21 } 22 } 23 } 24 25 return false; 26 } 27 28 public boolean dfs(char[][] board, int i, int j, String word, int wordIndex, boolean[][] visit) { 29 int rows = board.length; 30 int cols = board[0].length; 31 32 int len = word.length(); 33 if (wordIndex >= len) { 34 return true; 35 } 36 37 // the index is out of bound. 38 if (i < 0 || i >= rows || j < 0 || j >= cols) { 39 return false; 40 } 41 42 // the character is wrong. 43 if (word.charAt(wordIndex) != board[i][j]) { 44 return false; 45 } 46 47 // 不要訪問訪問過的節點 48 if (visit[i][j] == true) { 49 return false; 50 } 51 52 visit[i][j] = true; 53 54 // 遞歸 55 // move down 56 if (dfs(board, i + 1, j, word, wordIndex + 1, visit)) { 57 return true; 58 } 59 60 // move up 61 if (dfs(board, i - 1, j, word, wordIndex + 1, visit)) { 62 return true; 63 } 64 65 // move right 66 if (dfs(board, i, j + 1, word, wordIndex + 1, visit)) { 67 return true; 68 } 69 70 // move left 71 if (dfs(board, i, j - 1, word, wordIndex + 1, visit)) { 72 return true; 73 } 74 75 // 回溯 76 visit[i][j] = false; 77 return false; 78 } 79 }
Solution2:
與解1是一樣的,但我們可以省掉O(m*n)的空間復雜度。具體的作法是:在進入DFS后,把訪問過的節點置為'#',訪問完畢之后再置回來即可。

1 /* 2 * Solution 2: 可以省掉一個visit的數組 3 * */ 4 public boolean exist(char[][] board, String word) { 5 if (board == null || word == null 6 || board.length == 0 || board[0].length == 0) { 7 return false; 8 } 9 10 int rows = board.length; 11 int cols = board[0].length; 12 13 // i means the index. 14 for (int i = 0; i < rows; i++) { 15 for (int j = 0; j < cols; j++) { 16 // dfs all the characters in the matrix 17 if (dfs(board, i, j, word, 0)) { 18 return true; 19 } 20 } 21 } 22 23 return false; 24 } 25 26 public boolean dfs(char[][] board, int i, int j, String word, int wordIndex) { 27 int rows = board.length; 28 int cols = board[0].length; 29 30 int len = word.length(); 31 if (wordIndex >= len) { 32 return true; 33 } 34 35 // the index is out of bound. 36 if (i < 0 || i >= rows || j < 0 || j >= cols) { 37 return false; 38 } 39 40 // the character is wrong. 41 if (word.charAt(wordIndex) != board[i][j]) { 42 return false; 43 } 44 45 // mark it to be '#', so we will not revisit this. 46 board[i][j] = '#'; 47 48 // 遞歸 49 // move down 50 if (dfs(board, i + 1, j, word, wordIndex + 1)) { 51 return true; 52 } 53 54 // move up 55 if (dfs(board, i - 1, j, word, wordIndex + 1)) { 56 return true; 57 } 58 59 // move right 60 if (dfs(board, i, j + 1, word, wordIndex + 1)) { 61 return true; 62 } 63 64 // move left 65 if (dfs(board, i, j - 1, word, wordIndex + 1)) { 66 return true; 67 } 68 69 // 回溯 70 board[i][j] = word.charAt(wordIndex); 71 return false; 72 }
December 16th, 2014 重寫,簡潔一點點,11分鍾1次AC.
其實這里的回溯有一個點要注意,就是當dfs返回true時,我們並沒有回溯。原因是這時整個dfs就結束了,我們也就不需要再回溯。否則一般的遞歸/回溯結構
這里是需要先回溯再返回的。

1 public class Solution { 2 public boolean exist(char[][] board, String word) { 3 if (board == null || board.length == 0 || board[0].length == 0) { 4 return false; 5 } 6 7 int rows = board.length; 8 int cols = board[0].length; 9 for (int i = 0; i < rows; i++) { 10 for (int j = 0; j < cols; j++) { 11 // Check if there is a word begin from i,j. 12 if (dfs(board, word, i, j, 0)) { 13 return true; 14 } 15 } 16 } 17 18 return false; 19 } 20 21 public boolean dfs(char[][] board, String word, int i, int j, int index) { 22 int len = word.length(); 23 if (index >= len) { 24 return true; 25 } 26 27 // Check the input parameter. 28 if (i < 0 || i >= board.length || j < 0 || j >= board[0].length) { 29 return false; 30 } 31 32 // If the current character is right. 33 if (word.charAt(index) != board[i][j]) { 34 return false; 35 } 36 37 char tmp = board[i][j]; 38 board[i][j] = '#'; 39 40 // recursion. 41 if (dfs(board, word, i + 1, j, index + 1) 42 || dfs(board, word, i - 1, j, index + 1) 43 || dfs(board, word, i, j + 1, index + 1) 44 || dfs(board, word, i, j - 1, index + 1) 45 ) { 46 return true; 47 } 48 49 // backtrace. 50 board[i][j] = tmp; 51 return false; 52 } 53 }
雖然前面的方法可以AC,但考慮到最好不要更改入參的值,所以在return true前,我們還是加一個回溯代碼。

1 public class Solution { 2 public boolean exist(char[][] board, String word) { 3 if (board == null || board.length == 0 || board[0].length == 0) { 4 return false; 5 } 6 7 int rows = board.length; 8 int cols = board[0].length; 9 for (int i = 0; i < rows; i++) { 10 for (int j = 0; j < cols; j++) { 11 // Check if there is a word begin from i,j. 12 if (dfs(board, word, i, j, 0)) { 13 return true; 14 } 15 } 16 } 17 18 return false; 19 } 20 21 public boolean dfs(char[][] board, String word, int i, int j, int index) { 22 int len = word.length(); 23 if (index >= len) { 24 return true; 25 } 26 27 // Check the input parameter. 28 if (i < 0 || i >= board.length || j < 0 || j >= board[0].length) { 29 return false; 30 } 31 32 // If the current character is right. 33 if (word.charAt(index) != board[i][j]) { 34 return false; 35 } 36 37 char tmp = board[i][j]; 38 board[i][j] = '#'; 39 40 boolean ret = dfs(board, word, i + 1, j, index + 1) 41 || dfs(board, word, i - 1, j, index + 1) 42 || dfs(board, word, i, j + 1, index + 1) 43 || dfs(board, word, i, j - 1, index + 1); 44 45 // backtrace. 46 board[i][j] = tmp; 47 return ret; 48 } 49 }
GitHub代碼: