🚩传送门:力扣题目
力扣题目

题目

给定一个 [LC]12. 矩阵中的路径 - 图1 二维字符网格 [LC]12. 矩阵中的路径 - 图2和一个字符串单词 [LC]12. 矩阵中的路径 - 图3。如果[LC]12. 矩阵中的路径 - 图4存在于网格中,返回 [LC]12. 矩阵中的路径 - 图5 ;否则,返回[LC]12. 矩阵中的路径 - 图6
单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。

示例 1:
[LC]12. 矩阵中的路径 - 图7

输入:board = [[“A”,”B”,”C”,”E”],[“S”,”F”,”C”,”S”],[“A”,”D”,”E”,”E”]], word = “ABCCED” 输出:true

解题思路:DFS

本问题是典型的矩阵搜索问题,可使用 深度优先搜索(DFS) 解决。

复杂度分析

时间复杂度: [LC]12. 矩阵中的路径 - 图8 ,最差情况下,需要遍历矩阵中长度为 [LC]12. 矩阵中的路径 - 图9字符串的所有方案,其中 [LC]12. 矩阵中的路径 - 图10[LC]12. 矩阵中的路径 - 图11 分别是矩阵的行数和列数。

空间复杂度:[LC]12. 矩阵中的路径 - 图12 ,其中 [LC]12. 矩阵中的路径 - 图13为模式串长度,搜索过程中的递归深度不超过 [LC]12. 矩阵中的路径 - 图14

我的代码

  1. class Solution {
  2. public static boolean exist(char[][] board, String word) {
  3. if (board == null || board.length == 0) return false;
  4. if (word == null || word.equals("")) return false;
  5. // 标记是否被访问
  6. boolean[][] view = new boolean[board.length][board[0].length];
  7. // 遍历每一个点做起始位置dfs
  8. for (int i = 0; i < board.length; i++) {
  9. for (int j = 0; j < board[i].length; j++) {
  10. // 搜索到了匹配的
  11. if (dfs(board, word, i, j, view)) return true;
  12. }
  13. }
  14. // 搜索完毕所有可能未被访问
  15. return false;
  16. }
  17. private static boolean dfs(char[][] board, String word, int i, int j, boolean[][] view) {
  18. if (isvalid(board, i, j, view)) {
  19. // 判断是否相等
  20. if (board[i][j] != word.charAt(0)) return false;
  21. if(word.length()==1) return true;
  22. // 当前位置合法,先标记访问
  23. view[i][j] = true;
  24. // 定义4个方向,右下左上
  25. int[][] dir = new int[][]{{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
  26. for (int k = 0; k < dir.length; k++) {
  27. // 四个方向搜索,如果能搜索到就返回搜索到的结果
  28. if (dfs(board, word.substring(1), i + dir[k][0], j + dir[k][1], view))
  29. return true;
  30. }
  31. // 四个方向搜索完毕,放弃当前点(i,j),置为未访问
  32. view[i][j] = false;
  33. }
  34. return false;
  35. }
  36. private static boolean isvalid(char[][] board, int i, int j, boolean[][] view) {
  37. // 越界非法
  38. if (i < 0 || i >= board.length) return false;
  39. if (j < 0 || j >= board[i].length) return false;
  40. // 已被访问,蛇撞身体了
  41. if (view[i][j]) return false;
  42. // 合法的点(i,j)
  43. return true;
  44. }
  45. public static void main(String[] args) {
  46. char[][] board=new char[][]{{'A','B'}};
  47. System.out.println(exist(board, "BA"));
  48. }
  49. }

K 神代码

确实代码简化了很多

  1. class Solution {
  2. public boolean exist(char[][] board, String word) {
  3. char[] words = word.toCharArray();
  4. for (int i = 0; i < board.length; i++) {
  5. for (int j = 0; j < board[0].length; j++) {
  6. if (dfs(board, words, i, j, 0)) return true;
  7. }
  8. }
  9. return false;
  10. }
  11. boolean dfs(char[][] board, char[] word, int i, int j, int k) {
  12. // 边界合法性判断
  13. if (i >= board.length || i < 0 || j >= board[0].length || j < 0 || board[i][j] != word[k]) return false;
  14. if (k == word.length - 1) return true;
  15. // 通过修改board[i][j]达到访问标记的作用
  16. board[i][j] = '\0';
  17. // 四向搜索
  18. boolean res = dfs(board, word, i + 1, j, k + 1) || dfs(board, word, i - 1, j, k + 1) ||
  19. dfs(board, word, i, j + 1, k + 1) || dfs(board, word, i, j - 1, k + 1);
  20. // 取消访问标记,用word[k]恢复
  21. board[i][j] = word[k];
  22. return res;
  23. }
  24. }