【LeetCode剑指offer12】矩阵中的路径(dfs回溯)

简介: 递归参数: 当前字符在矩阵 grid 中的行索引 i 和列索引 j ,当前目标字符(匹配的)在目标字符串 word 中的索引 k 。

一、题目


image.pngimage.png


二、思路

递归参数: 当前字符在矩阵 grid 中的行索引 i 和列索引 j ,当前目标字符(匹配的)在目标字符串 word 中的索引 k 。

终止条件:

返回 false :当前字符和目标字符不匹配,需要return false没必要继续dfs了,而这里也可以不判断位置坐标是否越界,直接写到四个dfs前也行;

返回 true : 当前目标字符(匹配的)在目标字符串 word 中的索引 k = len(word) - 1 ,即目标字符串 word 已全部匹配;

递归过程:

标记访问过字符(方法一):单独设置visited二维布尔数组,如果访问过当前位置的元素,则赋值为true。

标记访问过字符(方法二): 将 grid[i][j] 修改为 ‘/’ ,代表此元素已访问过,防止之后搜索时重复访问。

搜索当前字符的下一单元格: 朝当前元素的 上、下、左、右 四个方向开启下层递归,并记录结果至布尔变量 flag 。

回溯当前字符: 将 board[i][j] 元素还原至初始值 。

返回值: 返回布尔量 result ,代表是否搜索到目标字符串。

三、代码

class Solution {
private:
    vector<pair<int,int>>directions{{0,1},{0,-1},{1,0},{-1,0}};
public:
    bool exist(vector<vector<char>>& grid, string word) {
        int high = grid.size();
        int width = grid[0].size();
        vector<vector<int>> visited(high, vector<int>(width));
        //分别从每个单词开始dfs
        for(int i = 0; i < high; i++){
            for(int j = 0; j < width; j++){
                bool flag = dfs(grid, visited, i, j, word, 0);
                if(flag){
                    return true;
                }
            }
        }
        return false;
    }
    bool dfs(vector<vector<char>>&grid, 
             vector<vector<int>>&visited, int i, int j,
             string& word, int k){
        if(grid[i][j] != word[k]){
            //当前字符不匹配
            return false;
        }
        if(k == word.length() - 1){
            //当前已经访问到末尾,即完成word匹配
            return true;
        }
        //标记访问过
        visited[i][j] = true;
        bool result = false;
        for(auto dir: directions){
            int x = i + dir.first, y = j + dir.second;
            //若没有越界
            if(isarea(grid, x, y)){
                //若没有访问过
                if(!visited[x][y]){
                    bool flag = dfs(grid, visited, x, y, word, k + 1);
                    if(flag){
                       result = true;
                       break; 
                    }
                }
            }
        }
        //恢复原状
        visited[i][j] = false;
        return result;
    }
    bool isarea(vector<vector<char>>&grid,int x,int y){//判断点是否在网格内
        if(x>=0 && x<grid.size() && 0<=y && y<grid[0].size()){
            return true;
        }else{
            return false;
        }
    }  
};
相关文章
【LeetCode 35】112.路径总和
【LeetCode 35】112.路径总和
107 0
|
6月前
|
Go 开发者 索引
【LeetCode 热题100】路径与祖先:二叉树中的深度追踪技巧(力扣33 / 81/ 153/154)(Go语言版)
本文深入探讨了LeetCode中四道关于「搜索旋转排序数组」的经典题目,涵盖了无重复和有重复元素的情况。通过二分查找的变形应用,文章详细解析了每道题的解题思路和Go语言实现代码。关键点包括判断有序区间、处理重复元素以及如何缩小搜索范围。文章还总结了各题的异同,并推荐了类似题目,帮助读者全面掌握二分查找在旋转数组中的应用。无论是初学者还是有经验的开发者,都能从中获得实用的解题技巧和代码实现方法。
276 14
|
5月前
|
分布式计算 算法 Go
【LeetCode 热题100】BFS/DFS 实战:岛屿数量 & 腐烂的橘子(力扣200 / 994 )(Go语言版)
本文讲解了两道经典的图论问题:**岛屿数量(LeetCode 200)** 和 **腐烂的橘子(LeetCode 994)**,分别通过 DFS/BFS 实现。在“岛屿数量”中,利用深度或广度优先搜索遍历二维网格,标记连通陆地并计数;“腐烂的橘子”则采用多源 BFS,模拟腐烂传播过程,计算最短时间。两者均需掌握访问标记技巧,是学习网格搜索算法的绝佳实践。
176 1
|
5月前
|
Go
【LeetCode 热题100】BFS/DFS 实战:岛屿数量 & 腐烂的橘子(力扣200 / 994 )(Go语言版)
本篇博客详细解析了三道经典的动态规划问题:198. 打家劫舍(线性状态转移)、279. 完全平方数与322. 零钱兑换(完全背包问题)。通过 Go 语言实现,帮助读者掌握动态规划的核心思想及其实战技巧。从状态定义到转移方程,逐步剖析每道题的解法,并总结其异同点,助力解决更复杂的 DP 问题。适合初学者深入理解动态规划的应用场景和优化方法。
120 0
|
7月前
|
Go
【LeetCode 热题100】路径与祖先:二叉树中的深度追踪技巧(力扣437 / 236 )(Go语言版)
本文深入探讨二叉树中路径与祖先问题,涵盖两道经典题目:LeetCode 437(路径总和 III)和236(最近公共祖先)。对于路径总和 III,文章分析了双递归暴力解法与前缀和优化方法,后者通过哈希表记录路径和,将时间复杂度从O(n²)降至O(n)。在最近公共祖先问题中,采用后序遍历递归查找,利用“自底向上”的思路确定最近公共祖先节点。文中详细解析代码实现与核心要点,帮助读者掌握深度追踪技巧,理解树结构中路径与节点关系的本质。这类问题在面试中高频出现,掌握其解法意义重大。
140 4
|
7月前
|
算法 Go
【LeetCode 热题100】深入理解二叉树结构变化与路径特性(力扣104 / 226 / 114 / 543)(Go语言版)
本博客深入探讨二叉树的深度计算、结构变换与路径分析,涵盖四道经典题目:104(最大深度)、226(翻转二叉树)、114(展开为链表)和543(二叉树直径)。通过递归与遍历策略(前序、后序等),解析每题的核心思路与实现方法。结合代码示例(Go语言),帮助读者掌握二叉树相关算法的精髓。下一讲将聚焦二叉树构造问题,欢迎持续关注!
164 10
|
7月前
|
算法 Go
【LeetCode 热题100】73:矩阵置零(详细解析)(Go语言版)
这篇文章详细解析了力扣热题 73——矩阵置零问题,提供两种解法:一是使用额外标记数组,时间复杂度为 O(m * n),空间复杂度为 O(m + n);二是优化后的原地标记方法,利用矩阵的第一行和第一列记录需要置零的信息,将空间复杂度降低到 O(1)。文章通过清晰的代码示例与复杂度分析,帮助理解“原地操作”及空间优化技巧,并推荐相关练习题以巩固矩阵操作能力。适合刷题提升算法思维!
176 9
【LeetCode 36】113.路径总和II
【LeetCode 36】113.路径总和II
104 0
【LeetCode 34】257.二叉树的所有路径
【LeetCode 34】257.二叉树的所有路径
96 0
|
Unix Shell Linux
LeetCode刷题 Shell编程四则 | 194. 转置文件 192. 统计词频 193. 有效电话号码 195. 第十行
本文提供了几个Linux shell脚本编程问题的解决方案,包括转置文件内容、统计词频、验证有效电话号码和提取文件的第十行,每个问题都给出了至少一种实现方法。
216 6
LeetCode刷题 Shell编程四则 | 194. 转置文件 192. 统计词频 193. 有效电话号码 195. 第十行