深搜练习(单词搜索)(12)

一.题目

79. 单词搜索 - 力扣(LeetCode)

二.思路讲解

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>>),但这里假设数据范围较小。

  • rowcol:成员变量,用于存储网格的行数和列数。

  • 方向数组 dx[4]dy[4]:表示上下左右四个方向的偏移量,方便探索相邻格子。

二、主函数 exist
  1. 首先获取网格的行数 row 和列数 col,并赋值给成员变量。

  2. 遍历整个网格,如果某个格子上的字符等于单词的第一个字符 word[0],则将其标记为已使用,并调用递归函数 dfs,从该格子出发,匹配单词的剩余部分(从下标 1 开始)。

  3. dfs 返回 true,则说明找到完整路径,直接返回 true;否则,撤销当前格子的标记(回溯),继续尝试下一个起点。

  4. 若所有起点都尝试完,则返回 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

四、回溯与恢复现场

回溯是本题的核心。当从某个格子出发的某条路径无法匹配时,必须将当前格子的标记恢复为未使用,以便其他路径可以重新经过它。

相关推荐
企客宝CRM2 小时前
2026年中小企业CRM选型指南:企客宝CRM处于什么位置?
android·算法·企业微信·rxjava·crm
橙淮2 小时前
二叉树核心概念与Java实现详解
数据结构·算法
大卡片2 小时前
C++的基础知识点
开发语言·c++
米罗篮2 小时前
DSU并查集 & 拓展欧几里得-逆元
c++·经验分享·笔记·算法·青少年编程
橙淮2 小时前
双指针法:高效算法解题的利器
算法
初心未改HD3 小时前
深度学习之MLP与反向传播算法详解
人工智能·深度学习·算法
刀法如飞3 小时前
【Go 字符串查找的 20 种实现方式,用不同思路解决问题】
人工智能·算法·go
谙弆悕博士3 小时前
【附C++源码】从零开始实现 2048 游戏
java·c++·游戏·源码·项目实战·2048