剑指 Offer 12. 矩阵中的路径(79. 单词搜索)
题目:
思路:
【1】思路:采用深度搜索,但首先还是要遍历一遍数组,将哪些下标与第一个字母对应的进行递归查找。【其次,重点在于边界值,数组的上下左右边界,字符的长度边界,还有深度遍历的话应该有一个类似动态规划的数据用于记录标志位,可以采用布尔值,但是布尔值是8bit的,改用int,4bit,更节约空间,0和1替代false和true】,最后考虑剪枝问题,如果不匹配的话,就不应该继续往该路径溢散,如果已经找到则应该提前返回。
代码展示:
另一版更优雅的精细写法:
//时间68 ms击败74.64% //内存39.3 MB击败80.82% class Solution { public boolean exist(char[][] board, String word) { if (board == null || board.length == 0 || board[0].length == 0) return false; char[] w = word.toCharArray(); for (int i = 0; i < board.length; i++) { for (int j = 0; j < board[0].length; j++) { if (doExist(board, w, i, j, 0)) return true; } } return false; } private boolean doExist(char[][] board, char[] w, int i, int j, int idx) { if (idx == w.length) return true; if (i < 0 || i >= board.length || j < 0 || j >= board[0].length || board[i][j] != w[idx]) return false; board[i][j] ^= 256; boolean res = doExist(board, w, i+1, j, idx+1) || doExist(board, w, i-1, j, idx+1) || doExist(board, w, i, j+1, idx+1) || doExist(board, w, i, j-1, idx+1); board[i][j] ^= 256; return res; } }
精细版本(虽然看着代码简短了很多,但是相对而言效率上貌似就降低了):
//时间178 ms击败7.91% //内存41.9 MB击败8.72% class Solution { public boolean exist(char[][] board, String word) { int h = board.length, w = board[0].length; int index = 0; int[][] flag = new int[h][w]; for (int i = 0; i < h; i++){ for (int j = 0; j < w; j++){ if (word.charAt(index) == board[i][j]) { flag[i][j] = 1; if (pathExist(board,i,h,j,w,word,index+1,word.length(),flag)) return true; flag[i][j] = 0; } } } return false; } public boolean pathExist(char[][] board, int h, int max_h, int w, int max_w ,String word , int index, int max_index, int[][] flag) { if (index >= max_index) return true; int height , wight; int[][] directions = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}}; for (int[] dir : directions){ height = h + dir[0]; wight = w + dir[1]; //保持边界不超出 if (wight >= 0 && wight < max_w && height >= 0 && height < max_h){ if (flag[height][wight] == 0 && board[height][wight] == word.charAt(index)){ flag[height][wight] = 1; if(pathExist(board,height,max_h,wight,max_w,word,index+1,max_index,flag)) return true; flag[height][wight] = 0; } } } return false; } }
粗略版本:
//时间60 ms击败97.55% //内存39.5 MB击败65.43% class Solution { public boolean exist(char[][] board, String word) { int h = board.length, w = board[0].length; int index = 0; int[][] flag = new int[h][w]; for (int i = 0; i < h; i++){ for (int j = 0; j < w; j++){ //遍历全部找出匹配的第一个字符 if (word.charAt(index) == board[i][j]) { //标记下标为使用 flag[i][j] = 1; if (pathExist(board,i,h,j,w,word,index+1,word.length(),flag)) return true; //当寻找完后要将下标复位 flag[i][j] = 0; } } } return false; } public boolean pathExist(char[][] board, int h, int max_h, int w, int max_w ,String word , int index, int max_index, int[][] flag) { if (index >= max_index) return true; int height , wight; //向左 height = h; wight = w-1; if (wight >= 0 && flag[height][wight] == 0 && board[height][wight] == word.charAt(index)){ flag[height][wight] = 1; if(pathExist(board,height,max_h,wight,max_w,word,index+1,max_index,flag)) return true; flag[height][wight] = 0; } //向右 height = h; wight = w+1; if (wight < max_w && flag[height][wight] == 0 && board[height][wight] == word.charAt(index)){ flag[height][wight] = 1; if(pathExist(board,height,max_h,wight,max_w,word,index+1,max_index,flag)) return true; flag[height][wight] = 0; } //向上 height = h-1; wight = w; if (height >= 0 && flag[height][wight] == 0 && board[height][wight] == word.charAt(index)){ flag[height][wight] = 1; if(pathExist(board,height,max_h,wight,max_w,word,index+1,max_index,flag)) return true; flag[height][wight] = 0; } //向下 height = h+1; wight = w; if (height < max_h && flag[height][wight] == 0 && board[height][wight] == word.charAt(index)){ flag[height][wight] = 1; if(pathExist(board,height,max_h,wight,max_w,word,index+1,max_index,flag)) return true; flag[height][wight] = 0; } return false; } }