【Hot 100】79. 单词搜索

请添加图片描述

  • 🙋‍♂️ 作者:海码007
  • 📜 专栏:算法专栏
  • 💥 标题:【Hot 100】79. 单词搜索
  • ❣️ 寄语:书到用时方恨少,事非经过不知难!

引言

单词搜索

  • 🎈 题目链接:
  • 🎈 做题状态:

我的解题

这道题就是dfs深度优先搜索了,找到满足条件的路径。找到起点位置,然后往四个方向进行dfs,并且使用 visited 记录走过的路径。并且 dfs 函数的返回值类型是 bool 类型,在遍历四个方向的时候如果结果为 true 就返回,如果不为true就继续遍历。

为什么这个属于回溯类型里面,因为 visited 数组以及 path路径需要回溯,也就是取消选择。

class Solution {
private:
    int direction[4][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} };
    bool dfs(vector<vector<char>>& board, string word, vector<vector<bool>>& visited, string& path, int sX, int sY)
    {
        if (path == word) 
        {
            return true;
        }

        int rows = board.size();
        int cols = board[0].size();

        // 遍历四个方向
        for (int i = 0; i < 4; ++i)
        {
            int nx = sX + direction[i][0];
            int ny = sY + direction[i][1];

            // 边界情况判断准确
            if (nx >= 0 && nx < rows && ny >= 0 && ny < cols && visited[nx][ny] == false && board[nx][ny] == word[path.size()])
            {
                path.push_back(board[nx][ny]);
                visited[nx][ny] = true;
                if ( dfs(board, word, visited, path, nx, ny) ) 
                {
                    return true;
                }
                path.pop_back();
                visited[nx][ny] = false;
            }
        }

        return false;
    }

public:
    bool exist(vector<vector<char>>& board, string word) {
        // 这道题有点像路径搜索了,感觉使用dfs可以查找满足要求的路径。
        for (int i = 0; i < board.size(); ++i)
        {
            for (int j = 0; j < board[0].size(); ++j)
            {
                if (board[i][j] == word[0])
                {
                    vector<vector<bool>> visited(board.size(), vector<bool>(board[0].size(), false));
                    string path;
                    path.push_back(word[0]);
                    visited[i][j] = true;
                    if ( dfs(board, word, visited, path, i, j) )
                    {
                        return true;
                    }
                }
            }
        }

        return false;
    }
};

代码分析

你写的这道 单词搜索(Word Search) 的 DFS 解法已经相当扎实了。整体架构合理、逻辑清晰,回溯控制准确,基本就是一道高质量的标准答案实现。下面我来帮你详细分析你的解题思路、优点、可以优化的地方


✅ 一、思路概述

你准确抓住了题目的核心:

从矩阵的每一个字符出发,尝试在四个方向上递归寻找下一个字符,直到组成目标字符串或回溯。

你的实现分为以下几个关键步骤:

  1. 枚举起点

遍历 board 中每个格子,找到所有可能的起点(即字符等于 word[0] 的点)开始 DFS。

  1. DFS + 回溯搜索路径

从当前点出发,向四个方向递归搜索,只要路径当前拼接的字符串等于 word,立即返回 true

  1. 剪枝条件
  • 越界判断;
  • 已访问判断(用 visited 标记);
  • 当前字符是否匹配下一个目标字符。
  1. 回溯操作
  • 添加字符 → 递归 → 回溯(撤销字符 + 撤销访问状态)。

✅ 二、代码优点

优点描述
🎯 核心思路准确DFS + 回溯的模式完全正确
👣 路径构造逻辑清晰path 字符串辅助构造路径,直观易懂
🔍 剪枝条件完整边界、字符匹配、访问状态都判断到了
🔄 回溯恢复彻底使用 visited[nx][ny] = falsepath.pop_back()
🔁 多起点尝试使用两层循环穷举起始点,覆盖所有可能路径

🧠 三、可以优化的地方(建议改进)

1. 省略 path,改用 index 记录搜索进度

你的实现使用了 string path 来构建路径,但其实只需要一个 int index 表示当前匹配到了 word[index]

bool dfs(vector<vector<char>>& board, const string& word, vector<vector<bool>>& visited, int x, int y, int index)
{
    if (index == word.size()) return true;

    // 越界 or 已访问 or 不匹配
    int rows = board.size(), cols = board[0].size();
    if (x < 0 || x >= rows || y < 0 || y >= cols || visited[x][y] || board[x][y] != word[index])
        return false;

    visited[x][y] = true;
    for (auto& dir : direction) {
        if (dfs(board, word, visited, x + dir[0], y + dir[1], index + 1))
            return true;
    }
    visited[x][y] = false;
    return false;
}

➡️ 优点:减少字符串构造和比较的开销,提升执行效率。


2. 提前返回优化:从递归中 return 的地方及时 return

你这块已经写得不错,不过更推荐使用:

if (dfs(...)) return true;

代替

bool found = dfs(...);
if (found) return true;

这可以在大型搜索空间下减少递归深度。


3. 使用全局方向数组时建议使用 const vector<pair<int,int>> 替代 C 数组

例如:

const vector<pair<int, int>> dirs = {{-1,0}, {1,0}, {0,-1}, {0,1}};

更符合现代 C++ 风格,安全性更高、可读性更好。


4. 避免重复构造 visited

你在每一个起点都重新构造 visited,可以提前构造好一个共享变量,然后在每次搜索前清空它(也可接受)。


🔁 四、优化后的示例代码

class Solution {
private:
    const vector<pair<int, int>> dirs = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};

    bool dfs(vector<vector<char>>& board, vector<vector<bool>>& visited,
             int x, int y, const string& word, int index)
    {
        if (index == word.size()) return true;

        int rows = board.size(), cols = board[0].size();
        if (x < 0 || x >= rows || y < 0 || y >= cols ||
            visited[x][y] || board[x][y] != word[index])
            return false;

        visited[x][y] = true;
        for (const auto& [dx, dy] : dirs) {
            if (dfs(board, visited, x + dx, y + dy, word, index + 1))
                return true;
        }
        visited[x][y] = false;
        return false;
    }

public:
    bool exist(vector<vector<char>>& board, string word) {
        int rows = board.size(), cols = board[0].size();
        vector<vector<bool>> visited(rows, vector<bool>(cols, false));

        for (int i = 0; i < rows; ++i)
            for (int j = 0; j < cols; ++j)
                if (board[i][j] == word[0] &&
                    dfs(board, visited, i, j, word, 0))
                    return true;

        return false;
    }
};

✅ 五、总结

项目评价
算法思路✅ 非常清晰,DFS + 回溯框架到位
实现完整性✅ 所有必要的判断和回溯都写到了
可优化点✅ 可省略 path,改用 index 表示搜索进度
编码风格🔄 可用现代 C++ 替换 C 风格数组,更现代化

你这道题已经掌握得很好了,若想提升代码质量与效率,建议考虑采用 index 方案进行优化。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值