一.题目

二.思路讲解
2.1 思路讲解
我们要在二维网格中找到一条路径,使得路径上的字符按顺序拼成给定的单词。核心思路如下:
-
第一步:寻找起点
遍历整个网格,如果某个格子上的字符等于单词的第一个字符,就从这个格子开始进行深度优先搜索。
-
第二步:向四周探索
从当前格子出发,可以向上、下、左、右四个方向移动(通过方向数组
dx, dy实现)。每移动一步,就匹配单词的下一个字符。由于同一个格子不能重复使用,我们需要一个标记数组来记录格子是否已被当前路径占用。 -
第三步:剪枝与合法性检查
在尝试向某个方向移动时,必须满足三个条件:
-
不越界 :新坐标
(x, y)在网格范围内。 -
未访问:该格子未被当前路径使用过。
-
字符匹配:格子上的字符等于单词中当前需要匹配的字符。
只有同时满足这三个条件,才能继续递归。
-
三.代码演示
cpp
class Solution {
public:
bool check[7][7];
int row,col;//行、列
bool exist(vector<vector<char>>& board, string word)
{
row = board.size(),col = board[0].size();
for(int i = 0;i < row;i++)
{
for(int j = 0;j < col;j++)
{
//判断是不是等于字符串的第一个字符
if(board[i][j] == word[0])
{
check[i][j] = true;//占位
if(dfs(board,i,j,word,1)) return true;
check[i][j] = false;
}
}
}
return false;
}
int dx[4] = {-1,0,1,0};
int dy[4] = {0,1,0,-1};
bool dfs(vector<vector<char>>& board,int i,int j,string& word,int pos)
{
//如果pos长度等于word的长度说明找到了
if(pos == word.size()) return true;
for(int k = 0;k < 4;k++)
{
int x = i + dx[k],y = j + dy[k];
//找合法的
if(x >= 0 && y >= 0 && x < row && y < col && !check[x][y] && board[x][y] == word[pos])
{
check[x][y] = true;//占位
if(dfs(board,x,y,word,pos + 1)) return true;
check[x][y] = false;
}
}
return false;
}
};
四.代码讲解
一、全局变量与数据结构
-
check[7][7]:标记数组,用于记录当前路径中哪些格子已被使用。由于题目未明确网格大小,固定7可能不够,实际应动态分配(如vector<vector<bool>>),但这里假设数据范围较小。 -
row、col:成员变量,用于存储网格的行数和列数。 -
方向数组
dx[4]、dy[4]:表示上下左右四个方向的偏移量,方便探索相邻格子。
二、主函数 exist
-
首先获取网格的行数
row和列数col,并赋值给成员变量。 -
遍历整个网格,如果某个格子上的字符等于单词的第一个字符
word[0],则将其标记为已使用,并调用递归函数dfs,从该格子出发,匹配单词的剩余部分(从下标 1 开始)。 -
若
dfs返回true,则说明找到完整路径,直接返回true;否则,撤销当前格子的标记(回溯),继续尝试下一个起点。 -
若所有起点都尝试完,则返回
false。
三、递归函数 dfs
递归函数 dfs(board, i, j, word, pos) 表示当前在格子 (i, j) 上,已经匹配到了单词的第 pos 个字符(即 word[pos-1] 已匹配,现在需要匹配 word[pos])。返回布尔值表示是否能从当前位置继续匹配完剩余单词。
1. 递归终止条件
如果 pos == word.size(),说明已经成功匹配了所有字符,返回 true。
2. 向四个方向探索
使用 for 循环遍历四个方向,计算新坐标 (x, y)。对于每个方向,检查是否合法:
-
边界检查 :
x >= 0 && x < row && y >= 0 && y < col。 -
未访问检查 :
!check[x][y](该格子未被当前路径使用过)。 -
字符匹配 :
board[x][y] == word[pos]。
如果三个条件都满足,则:
-
将
(x, y)标记为已使用(check[x][y] = true)。 -
递归调用
dfs(board, x, y, word, pos+1)。 -
若递归返回
true,则直接返回true。 -
若递归返回
false,则回溯 :撤销标记(check[x][y] = false),继续尝试下一个方向。
3. 全部方向失败
如果四个方向都探索完仍无法匹配,则返回 false。
四、回溯与恢复现场
回溯是本题的核心。当从某个格子出发的某条路径无法匹配时,必须将当前格子的标记恢复为未使用,以便其他路径可以重新经过它。