思路及解答DFS回溯 主要的思路是对于每⼀个字符为起点递归向四周拓展然后遇到不匹配返回 false 匹配则接着匹配直到完成⾥⾯包含了 回溯 的思想。步骤如下针对每⼀个字符为起点初始化⼀个和矩阵⼀样⼤⼩的标识数组标识该位置是否被访问过⼀开始默认是false 。如果当前的字符索引已经超过了字符串⻓度说明前⾯已经完全匹配成功直接返回 true如果⾏索引和列索引不在有效的范围内或者改位置已经标识被访问直接返回 false否则将当前标识置为已经访问过如果矩阵当前位置的字符和字符串相等那么就字符串的索引加⼀递归判断周边的四个只要⼀个的结果为 true 就返回 true 否则将该位置置为没有访问过相当于回溯退回上⼀步返回 false 。矩阵当前位置的字符和字符串不相等否则同样也是将该位置置为没有访问过相当于回溯退回上⼀步返回 false 。⽐如查找 bcced :javapublic class Solution { public boolean hasPath(char[][] matrix, String word) { // write code here if (matrix null || word null || word.length() 0) { return false; } for (int i 0; i matrix.length; i) { for (int j 0; j matrix[0].length; j) { boolean[][] flags new boolean[matrix.length][matrix[0].length]; boolean result judge(i, j, matrix, flags, word, 0); if (result) { return true; } } } return false; } public boolean judge(int i, int j, char[][] matrix, boolean[][] flags, String words, int index) { if (index words.length()) { return true; } if (i 0 || j 0 || i matrix.length || j matrix[0].length || flags[i][j]) { return false; } flags[i][j] true; if (matrix[i][j] words.charAt(index)) { if (judge(i - 1, j, matrix, flags, words, index 1) || judge(i 1, j, matrix, flags, words, index 1) || judge(i, j 1, matrix, flags, words, index 1) || judge(i, j - 1, matrix, flags, words, index 1)) { return true; } else { flags[i][j] false; return false; } } else { flags[i][j] false; return false; } } }时间复杂度O(3^k × m × n)其中k为单词长度m、n为矩阵尺寸。每个点有3个方向可选不能回退空间复杂度O(k)递归栈深度和visited数组空间方向数组优化使用额外的访问标记数组来记录路径状态。javapublic class Solution { public boolean exist(char[][] board, String word) { if (board null || board.length 0 || board[0].length 0 || word null) { return false; } int m board.length, n board[0].length; boolean[][] visited new boolean[m][n]; char[] words word.toCharArray(); // 遍历矩阵中的每个单元格作为起始点 for (int i 0; i m; i) { for (int j 0; j n; j) { if (dfs(board, visited, words, i, j, 0)) { return true; } } } return false; } private boolean dfs(char[][] board, boolean[][] visited, char[] word, int i, int j, int index) { // 终止条件1找到完整路径 if (index word.length) { return true; } // 终止条件2越界或已访问或字符不匹配 if (i 0 || i board.length || j 0 || j board[0].length || visited[i][j] || board[i][j] ! word[index]) { return false; } // 标记当前单元格为已访问 visited[i][j] true; // 向四个方向进行DFS搜索 boolean found dfs(board, visited, word, i 1, j, index 1) || // 向下 dfs(board, visited, word, i - 1, j, index 1) || // 向上 dfs(board, visited, word, i, j 1, index 1) || // 向右 dfs(board, visited, word, i, j - 1, index 1); // 向左 // 回溯恢复访问状态 visited[i][j] false; return found; } }时间复杂度O(3^k × m × n)其中k为单词长度m、n为矩阵尺寸。每个点有3个方向可选不能回退空间复杂度O(k)递归栈深度和visited数组空间时间空间复杂度与方法一相同但代码更易扩展如需要八方向移动时只需修改DIRECTIONS数组原地标记优化最优通过修改原矩阵来标记访问状态节省空间。javapublic class Solution { public boolean exist(char[][] board, String word) { if (board null || board.length 0 || word null || word.length() 0) { return false; } char[] words word.toCharArray(); for (int i 0; i board.length; i) { for (int j 0; j board[0].length; j) { if (dfsOptimized(board, words, i, j, 0)) { return true; } } } return false; } private boolean dfsOptimized(char[][] board, char[] word, int i, int j, int index) { // 边界检查和字符匹配检查 if (i 0 || i board.length || j 0 || j board[0].length || board[i][j] ! word[index]) { return false; } // 找到完整路径 if (index word.length - 1) { return true; } // 原地标记将当前字符临时替换为特殊标记不能出现的字符 char temp board[i][j]; board[i][j] #; // 标记为已访问 // 四个方向搜索 boolean res dfsOptimized(board, word, i 1, j, index 1) || dfsOptimized(board, word, i - 1, j, index 1) || dfsOptimized(board, word, i, j 1, index 1) || dfsOptimized(board, word, i, j - 1, index 1); // 回溯恢复原始字符 board[i][j] temp; return res; }