剑指 Offer 12. 矩阵中的路径 - 力扣(LeetCode)

给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中,返回 true ;否则,返回 false 。

单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。

思路:


  1. 标准矩阵搜索回溯模板 细节很多

复杂度:

宽松上界为 O(m n * 3^L^) L为字符串长度

题解:

class Solution {
public:
    //两个函数,需要把第一个函数传入的内容定义为全局变量以便dfs函数调用
    int ax[4]={0,0,1,-1},ay[4]={1,-1,0,0};//快速位移数组
    vector<vector<char>> myboard;
    string myword;
    int n,m;
    int check[10][10];//m n < 10
    

    bool dfs(int x,int y,int k){
        if(k==0)//这种写法不会将传入点记入check,需要手动实现
            check[x][y]=1;
        if(myword[k]!=myboard[x][y])//判定1 字母不同
            return false;
        if(k==myword.size()-1)//判定2 字母相同且长度完整
            return true;
        for(int i=0;i<4;i++){//四个方向 其实是三个不包含原来的
            int rx=x+ax[i],ry=y+ay[i];
            if(rx>=n||rx<0||ry>=m||ry<0||check[rx][ry])
                continue;//剪枝
            
            check[rx][ry]=1;//标记
            bool res=dfs(rx,ry,k+1);//长度++
            check[rx][ry]=0;//回溯
            if(res)//只要有一条路成功即可
                return true;
        }
        if(k==0)//无论在哪都要回溯回来
            check[x][y]=0;
        return false;
    }
    bool exist(vector<vector<char>>& board, string word) {
        myboard=board;
        myword=word;

        n=board.size();
        if(n==0) return false;//特判
        m=board[0].size();

        if(word.size()==0) return true;//特判
        char start=word[0];//首字母
        memset(check,0,sizeof(check));

        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                if(board[i][j]==start){//匹配首字母减少用时,不必要,在dfs中同样有,写的时候菜了
                    if(dfs(i,j,0))
                        return true;
                }
            }
        }
        return false;
    }
};