1. 题目
考察点
这道题的考察点是回溯法(backtracking)的应用。回溯法是一种常用的算法思想,它可以解决很多和搜索、组合、排列、子集、路径等相关的问题。回溯法的核心是递归和剪枝,递归是为了遍历所有可能的选择,剪枝是为了减少无效的选择,提高效率。回溯法需要掌握以下几个要点:
- 如何定义状态空间,也就是所有可能的选择。
- 如何定义递归函数,也就是回溯的过程。
- 如何定义终止条件,也就是找到一个解或者遍历完所有选择。
- 如何定义剪枝条件,也就是排除一些不满足条件的选择。
- 如何记录和恢复状态,也就是标记和取消标记访问过的位置。
这道题是一个典型的回溯法的问题,它要求我们在一个字符矩阵中寻找一个单词,我们可以把每个位置看作一个状态,每个方向看作一个选择,然后用回溯法来搜索所有可能的路径,如果找到一个匹配的单词,就返回true,否则返回false。我们需要注意边界条件和剪枝条件,以及如何记录和恢复访问矩阵。
2. 解法
思路
我的思路是使用回溯法(backtracking),也就是一种深度优先搜索(DFS)的变形,来在矩阵中寻找单词。回溯法的基本思想是,从一个起点开始,尝试所有可能的选择,如果发现某个选择不满足条件,就回退到上一个状态,继续尝试其他选择,直到找到一个满足条件的解或者遍历完所有选择。
代码逻辑
我的代码逻辑如下:
- 首先,检查边界情况,如果矩阵或单词为空,直接返回false。
- 然后,获取矩阵的行数和列数,并创建一个布尔矩阵来标记访问过的位置。
- 接着,遍历矩阵,对于每个位置,如果它和单词的第一个字符匹配,就调用一个辅助方法backtrack来进行回溯。如果backtrack返回true,说明找到了一个匹配的单词,就返回true。如果遍历完矩阵都没有找到匹配的单词,就返回false。
- 最后,定义辅助方法backtrack,它接收矩阵、单词、当前位置、当前索引和访问矩阵作为参数。它的逻辑如下:
- 检查基本情况,如果索引达到了单词的长度,说明已经找到了一个匹配的单词,就返回true。
- 检查边界条件,如果当前位置超出了矩阵的范围,或者已经访问过了,或者不和当前字符匹配,就返回false。
- 标记当前位置为已访问。
- 尝试四个方向:上、下、左、右,对于每个方向,递归调用backtrack,并将索引加一。如果任何一个方向返回true,就将结果赋值为true。
- 取消标记当前位置为已访问。
- 返回结果。
这样,就完成了回溯法的实现。希望这能帮助你理解我的代码。如果你还有其他问题,请随时提问。
具体实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | class Solution { public boolean exist( char [][] board, String word) { // 检查边界情况 if (board == null || board.length == 0 || board[ 0 ].length == 0 || word == null || word.length() == 0 ) { return false ; } // 获取矩阵的维度 int m = board.length; int n = board[ 0 ].length; // 创建一个布尔矩阵来标记访问过的位置 boolean [][] visited = new boolean [m][n]; // 遍历矩阵,尝试从每个位置开始寻找单词 for ( int i = 0 ; i < m; i++) { for ( int j = 0 ; j < n; j++) { // 如果第一个字符匹配,开始回溯 if (board[i][j] == word.charAt( 0 )) { if (backtrack(board, word, i, j, 0 , visited)) { return true ; } } } } // 如果没有找到匹配,返回false return false ; } // 辅助方法,执行回溯 private boolean backtrack( char [][] board, String word, int i, int j, int index, boolean [][] visited) { // 检查基本情况:如果索引达到单词的末尾,我们已经找到了一个匹配 if (index == word.length()) { return true ; } // 检查边界条件:如果位置超出范围或已经访问过或不匹配当前字符,返回false if (i < 0 || i >= board.length || j < 0 || j >= board[ 0 ].length || visited[i][j] || board[i][j] != word.charAt(index)) { return false ; } // 标记当前位置为已访问 visited[i][j] = true ; // 尝试四个方向:上,下,左,右 boolean res = backtrack(board, word, i - 1 , j, index + 1 , visited) || backtrack(board, word, i + 1 , j, index + 1 , visited) || backtrack(board, word, i, j - 1 , index + 1 , visited) || backtrack(board, word, i, j + 1 , index + 1 , visited); // 取消标记当前位置为已访问 visited[i][j] = false ; // 返回结果 return res; } } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)
2019-04-29 Spring 框架用到的 9 个设计模式汇总!
2019-04-29 设计模式总结
2019-04-29 spring中的设计模式
2019-04-29 深入解析spring中用到的九种设计模式