1. 题⽬链接:79.单词搜索
2. 题⽬描述:
3. 解法:
算法思路:
我们需要假设每个位置的元素作为第⼀个字⺟,然后向相邻的四个⽅向进⾏递归,并且不能出现重复 使⽤同⼀个位置的元素。通过深度优先搜索的⽅式,不断地枚举相邻元素作为下⼀个字⺟出现的可能 性,并在递归结束时回溯,直到枚举完所有可能性,得到正确的结果。
递归函数设计:bool dfs(int x, int y, int step, vector>& board, string word, vector>& vis, int &n, int &m, int &len)
参数:x(当前需要进⾏处理的元素横坐标),y(当前需要进⾏处理的元素横坐标),step(当前已 经处理的元素个数),word(当前的字符串状态);
返回值:当前坐标元素作为字符串中下标step的元素出现是否可以找到成⽴的字符串。
函数作⽤:判断当前坐标的元素作为字符串中下标step的元素出现时,向四个⽅向传递,查找是否存 在路径结果与字符串相同。
递归函数流程:
1. 遍历每个位置,标记当前位置并将当前位置的字⺟作为⾸字⺟进⾏递归,并且在回溯时撤回标记。
2. 在每个递归的状态中,我们维护⼀个步数step,表⽰当前已经处理了⼏个字⺟。
◦ 若当前位置的字⺟与字符串中的第step个字⺟不相等,则返回false。
◦ 若当前step的值与字符串⻓度相等,表⽰存在⼀种路径使得word成⽴,返回true。
3. 对当前位置的上下左右四个相邻位置进⾏递归,若递归结果为true,则返回true。
4. 若相邻的四个位置的递归结果都为false,则返回false。
• 特别地,如果使⽤将当前遍历到的字符赋值为空格,并在回溯时恢复为原来的字⺟的⽅法,则在递 归时不会重复遍历当前元素,可达到不使⽤标记数组的⽬的。
C++算法代码:
class Solution
{
public:
bool t[10][10] = { false }; //状态数组
int dx[4] = { 1,0,-1,0 };
int dy[4] = { 0,1,0,-1 };
bool dfs(vector<vector<char>>& board, string word, int x, int y, int s)
{
//出口
if (s == word.size())
{
return true;
}
//找数
for (int i = 0; i < 4; i++)
{
//改变后临时参数
int X = x + dx[i], Y = y + dy[i];
//合法判断
if (X < 0 || X >= board.size() || Y < 0 || Y >= board[0].size() || t[X][Y])
{
continue;
}
//找到数据
if (board[X][Y] == word[s])
{
t[X][Y] = true;
if (dfs(board, word, X, Y, s + 1) == true)
{
t[X][Y] = false;
return true;
}
else
{
t[X][Y] = false;
continue;
}
}
}
//没找到则不符合,返回上一层
return false;
}
bool exist(vector<vector<char>>& board, string word)
{
//获取开始地址
for (int i = 0; i < board.size(); i++)
{
for (int j = 0; j < board[0].size(); j++)
{
if (board[i][j] == word[0])
{
t[i][j]=true;
//如果找到了则返回true,没有的话恢复现场继续找
if(dfs(board,word,i,j,1)==true)
{
return true;
}
t[i][j]=false;
}
}
}
//一直没有找到则其中没有单词
return false;
}
};
Java算法代码:
class Solution
{
boolean[][] vis;
int m, n;
char[] word;
public boolean exist(char[][] board, String _word)
{
m = board.length; n = board[0].length;
word = _word.toCharArray();
vis = new boolean[m][n];
for (int i = 0; i < m; i++)
for (int j = 0; j < n; j++)
{
if (board[i][j] == word[0])
{
vis[i][j] = true;
if (dfs(board, i, j, 1)) return true;
vis[i][j] = false;
}
}
return false;
}
int[] dx = { 0, 0, 1, -1 };
int[] dy = { 1, -1, 0, 0 };
public boolean dfs(char[][] board, int i, int j, int pos)
{
if (pos == word.length)
{
return true;
}
// 上下左右去匹配 word[pos]
// 利⽤向量数组,⼀个 for 搞定上下左右四个⽅向
for (int k = 0; k < 4; k++)
{
int x = i + dx[k], y = j + dy[k];
if (x >= 0 && x < m && y >= 0 && y < n && !vis[x][y] && board[x][y]
== word[pos])
{
vis[x][y] = true;
if (dfs(board, x, y, pos + 1)) return true;
vis[x][y] = false;
}
}
return false;
}
}