剑指刷题日记剑指 剑指 Offer 12. 矩阵中的路径

题目描述

题目链接:https://leetcode-cn.com/problems/ju-zhen-zhong-de-lu-jing-lcof/
在这里插入图片描述

解题思路

深度优先搜索,每访问一个数,都可以当作DFS的入口。然后递归再访问它的上下左右四个邻居,根据其是否与字符串中的字符是否匹配决定是否继续搜索。匹配成功就继续搜索邻居,不成功就返回False。当匹配长度等于字符串长度时就说明存在一条通路了,这时候便可返回True。
需要注意,每访问一个结点,要深搜其邻居前要换成其他字符(标记为已经访问)。然后搜索之后再变回原来的字符(撤回标记)。为什么要这么操作呢?可以由下图简单理解。
在这里插入图片描述

为什么要添加标记?
退一步走,假设A是B的邻居,那么A递归深搜时可以访问B,如果A没有标记为已经访问,那么B递归深搜时又可以访问A,然后A又递归深搜B。。。以此无穷尽也,这也是为什么标记的作用了。用大白话讲,我是你大哥,你就只能是我小弟。不能你是我大哥,我也是你大哥。
为什么又要撤回标记?
而撤回标记,则代表以A为入口进行深搜时找不到匹配的通路,但是不单表A不能作为其他位置字符入口进行深搜时一个可行的通路呀。如上图所示。用白话讲就是,我当不了大哥,但是我可以当小弟呀。

解答代码如下:

class Solution {
public:
    bool exist(vector<vector<char>>& board, string word) {
        for(int i=0; i<board.size(); ++i)  //  行坐标
            for(int j=0; j<board[0].size(); ++j)  // 列坐标
            // 找到某入口位置,能够通这条路径
            {
                if (board[i][j] == word[0] && dfs(board, word, 0, i,j))
                        return true;     // 优化,找准入口再深搜  优化不了多少
            }
        return false;
    }

    bool dfs(vector<vector<char>>& board, string word, int len, int x, int y)
    {

        if(x<0 || y<0 || x>=board.size() || y>=board[0].size()|| board[x][y]!=word[len])
            // 坐标越界或者字符不匹配
            // 先判断坐标越界,因为本来就已经越界了的话,还访问board[x][y]就会报错
            return false;
		
		// 能执行下面的语句表明当前字符是匹配的
        // 递归先写返回条件
        if(len == word.size()-1)    // len表示当前匹配长度
            return true;
        
        // 字符匹配,先标记当前位置,表示已经走过
        // 因为该结点也是它邻居的邻居,深搜的话就死循环了 = =
        char temp = board[x][y];
        board[x][y] = '*';
        // 深搜其四个邻居,上下左右
        // 如果坐标越界,刚进入就会返回false,所以这里不需要再次判断越界
        int dx[4]={-1,1,0,0}, dy[4]={0,0,-1,1};
        for(int i=0;i<4;++i)
        {
            if(dfs(board, word, len+1, x+dx[i], y+dy[i]))
                return true;
        }

        // 四条路没一个走的通,那么就换一个入口试试,所以返回false之前恢复该入口。
        board[x][y] = temp;
        return false;
     }
};

深搜邻居的时候我也尝试过像其他网友这样
在这里插入图片描述
然后return res。 但是好像这样时间和空间都不如for循环依次访问。

下面这位大佬给出了加速小技巧,也可以学习一下
在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值