作者简介:
👨🎓一位20级的计科专业的新手,请各位大佬多多指教
🏡个人主页:XiaoChen_Android
📚学习专栏:力扣专栏
🕒发布日期:2022/8/6
『LeetCode|每日一题』单词搜索
1.每日一题
2.解题思路
2.1 思路分析
此题可以用dfs解决也可以用回溯法解决,我选择了回溯法,它只是比dfs多了一步--撤销修改节点访问状态
S1:回溯部分的核心传参就是网格的位置i和j,能继续往下找字母需满足以下几个条件:
1.不能越界;
2.还没有找全单词所有的字母,即find的值还是false(find定义为全局变量以便于修改它的值);
3.(i,j)这个点没有被访问过;
4.当前字母和目标字母应相等。
(读者可仔细想一下这几个条件,只有满足这几个条件才有继续回溯的必要)
S2:判断结束条件---当标志位flag = word.length() - 1时,说明刚好找到这个单词,则结束回溯;
S3:由于每个点有四个方向可以走,所以分四种情况,(i + 1 , j) (i - 1 , j) (i , j + 1) (i , j - 1),这四种情况应都尝试;
S4:最后通过find的值来判断能否找到该字母
2.2 核心代码(回溯)
//flag: 记录目标单词的字符索引,只有棋盘格字符和flag指向的字符一致时,才有机会继续搜索接下来的字符;如果flag已经过了目标单词的尾部了,那么便说明找到目标单词了
private static void back(int i,int j,String word,char[][] board,boolean[][] used,int flag){
//超出边界、已经访问过、单词已找到、找到的字符和目标字符不相等则直接返回
if(i < 0 || i >= board.length || j < 0 || j >= board[0].length || used[i][j]
|| find || word.charAt(flag) != board[i][j]) return ;
//如果flag == word.length() - 1,则说明已经找到了
if(flag == word.length() - 1){
find = true;
return ;
}
//遍历四个方向
used[i][j] = true;
back(i + 1,j,word,board,used,flag + 1);
back(i - 1,j,word,board,used,flag + 1);
back(i,j + 1,word,board,used,flag + 1);
back(i,j - 1,word,board,used,flag + 1);
//撤销已访问
used[i][j] = false;
}
2.3 全部代码
class Solution {
static boolean find;
public boolean exist(char[][] board, String word) {
if(board == null) return false;
int r = board.length;
int c = board[0].length;
boolean[][] used = new boolean[r][c]; //记录点有没有被访问
int flag = 0;
find = false;
//开始遍历
for(int i = 0; i < r; i++){
for(int j = 0; j < c; j++){
back(i,j,word,board,used,flag);
}
}
return find;
}
//flag: 记录目标单词的字符索引,只有棋盘格字符和flag指向的字符一致时,才有机会继续搜索接下来的字符;如果flag已经过了目标单词的尾部了,那么便说明找到目标单词了
private static void back(int i,int j,String word,char[][] board,boolean[][] used,int flag){
//超出边界、已经访问过、单词已找到、找到的字符和目标字符不相等则直接返回
if(i < 0 || i >= board.length || j < 0 || j >= board[0].length || used[i][j]
|| find || word.charAt(flag) != board[i][j]) return ;
//如果flag == word.length() - 1,则说明已经找到了
if(flag == word.length() - 1){
find = true;
return ;
}
//遍历四个方向
used[i][j] = true;
back(i + 1,j,word,board,used,flag + 1);
back(i - 1,j,word,board,used,flag + 1);
back(i,j + 1,word,board,used,flag + 1);
back(i,j - 1,word,board,used,flag + 1);
//撤销已访问
used[i][j] = false;
}
}
🍁 类似题目推荐:
如果文章对你有帮助就支持一下噢,新手尝试,如有不好的地方请各位大佬多多指教!