矩阵中的路径

前言

这道题我折腾了一个半~两个小时,终于AC了,特此纪念. 

题目描述

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

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

例如,在下面的 3×4 的矩阵中包含单词 "ABCCED"(单词中的字母已标出)。

示例 1:

输入:board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "ABCCED"
输出:true
示例 2:

输入:board = [["a","b"],["c","d"]], word = "abcd"
输出:false
 

提示:

1 <= board.length <= 200
1 <= board[i].length <= 200
board 和 word 仅由大小写英文字母组成
 

注意:本题与主站 79 题相同:https://leetcode-cn.com/problems/word-search/

通过次数193,140提交次数426,673描述

思路

老样子,递归三部曲:

返回逻辑:当前index(size)下的字符和word[index]下的字符不一样,或者已经找到了满足条件的情况.

处理逻辑:设置访问位为true,同时往字符串中push_back(),如果两个字符串相等,就使得flag=1,返回,如果字符串长度不等,再向四周DFS.最后再回溯使得str.pop_back(),vis[i][j]=false;

返回值:void 

代码


class Solution {
public:
    int m, n;
    int a[4] = {-1,1,0,0};  //行,上下左右
    int b[4] = {0,0,-1,1};  //列,上下左右
    int flag = 0;
    int len;
    bool equal(string& str1, string& str2) {
        int size1 = str1.size();
        int size2 = str2.size();
        if (size1 != size2)    return false;
        for (int i = 0; i < size1; ++i) {
            if (str1[i] != str2[i])    return false;
        }
        return true;
    }

    void dfs(int i, int j, vector<vector<char>>& board, string word, vector<vector<bool>>& vis,string& str,int size) {
        if (flag)    return;
        str.push_back(board[i][j]);
        vis[i][j] = true;
        if (str[size] != word[size]) {
            str.pop_back();
            vis[i][j] = false;
            return; 
        }
        if (size==len-1) {
            if (equal(str, word)) {
                flag = 1;
                return;
            }
            else {
                str.pop_back();
                vis[i][j] = false;
                return;
            }
        }
        for (int k = 0; k < 4; ++k) {
                int x = i + a[k];
                int y = j + b[k];
                if (x < 0 || y < 0 || x >= m || y >= n || vis[x][y])  continue;
                dfs(x, y, board, word, vis, str,size+1);
        }
        str.pop_back();
        vis[i][j] = false;
    }

    bool exist(vector<vector<char>>& board, string word) {
        m = board.size();
        n = board[0].size();
        vector<vector<bool>> vis(m, vector<bool>(n, false));
        string str;
        len = word.size();
        for (int i = 0; i < m; ++i) {
            for (int j = 0; j < n; ++j) {
                if (flag)    return true;
                dfs(i, j, board, word, vis, str,0);
            }
        }
        if (flag)    return true;
        return false;
    }
};

小结

回溯法虽然有模板,但是还是因为逻辑条件较复杂导致的考虑不周全而总是出错,我们还是需要多多动手实践,遇到不会的地方,一步一步调试,把有觉得有问题的变量都打印下来,不仅锻炼了逻辑思维还锻炼了DEBUG能力. 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Shallow_Carl

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值