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

一、题目

在这里插入图片描述
在这里插入图片描述

二、思路

  • 递归参数: 当前字符在矩阵 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;
        }
    }  
};

猜你喜欢

转载自blog.csdn.net/qq_35812205/article/details/123932592