剑指offer 12. 矩阵中的路径

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

目录

非递归写法(含注释)

运行结果

递归写法

运行结果 


非递归写法(含注释)

class Solution {
    enum class direction { N, U, D, L, R };   //null, up, down, left, right
    struct Ltr {    //记录每个位置的坐标,以及下一次应该检查的方向
        int x, y;
        direction dir;
        Ltr(int X, int Y, direction d) : x(X), y(Y), dir(d) {}
    };
public:
    bool exist(vector<vector<char>>& board, string word) {
        size_t Row = board.size(), Col = board[0].size();
        vector<vector<bool>> visited(Row);
        for (auto& r : visited) r = vector<bool>(Col);

        for (int i = 0; i < Row; ++i) {
            for (int j = 0; j < Col; ++j) {
                if (board[i][j] == word[0]) {   //如果在矩阵中找到了第一个字符
                    if (match(board, visited, word, i, j)) return true;
                }
            }
        }
        return false;
    }

    bool match(const vector<vector<char>>& board, vector<vector<bool>>& visited, const string& word, int x, int y) {
        stack<Ltr> lstk;    //记录已访问过的位置的栈
        visited[x][y] = true;
        int pathlength = 0; //当前路径的长度
        direction dir = direction::U;   //应该检查的方向

        while (pathlength >= 0 && pathlength < word.length() - 1) {
            switch (dir) {
            case direction::U:  //上
                dir = direction::D;  //检查完一个方向,无论匹配与否,都要转向下一个方向
                if (matched(board, visited, word[pathlength + 1], x - 1, y)) {   //pos位置表示已经匹配但还未进栈的位置,pos+1表示有待检查的位置
                    handle(lstk, x--, y, dir, pathlength); //处理lstk, dir和pos
                    break;
                }
            case direction::D:  //下
                dir = direction::L;
                if (matched(board, visited, word[pathlength + 1], x + 1, y)) {
                    handle(lstk, x++, y, dir, pathlength);
                    break;
                }
            case direction::L:  //左
                dir = direction::R;
                if (matched(board, visited, word[pathlength + 1], x, y - 1)) {
                    handle(lstk, x, y--, dir, pathlength);
                    break;
                }
            case direction::R:  //右
                dir = direction::N;
                if (matched(board, visited, word[pathlength + 1], x, y + 1)) {
                    handle(lstk, x, y++, dir, pathlength);
                    break;
                }
            case direction::N:
                visited[x][y] = false;
                --pathlength;
                if (!lstk.empty()) { //从栈中弹出上一个字符,接着上一个字符进行操作
                    x = lstk.top().x, y = lstk.top().y;
                    dir = lstk.top().dir;
                    lstk.pop();
                }
            }
        }
        return pathlength == word.length() - 1 ? true : false;
    }

    bool matched(const vector<vector<char>>& board, vector<vector<bool>>& visited, const char& c, const int& x, const int& y) {
        if (x < 0 || x >= board.size() || y < 0 || y >= board[0].size()) return false; //下标越界
        if (visited[x][y] || board[x][y] != c) return false;  //已经检查过或者不匹配
        visited[x][y] = true;
        return true;
    }

    void handle(stack<Ltr>& stk, const int& x, const int& y, direction& dir, int& pathlength) {
        ++pathlength;
        stk.push(Ltr(x, y, dir));  //当前字符的位置和下次回到该位置要继续检查的方向 进栈
        dir = direction::U;    //当前位置匹配之后要进行下一个位置的匹配,需要重置方向
    }
};

运行结果

 

递归写法

class Solution {
public:
    bool exist(vector<vector<char>>& board, string word) {
        int rows = board.size(), cols = board[0].size();
        vector<vector<bool>> visited(rows);
        for (auto& r : visited) r = vector<bool>(cols);

        for (int i = 0; i < rows; ++i) {
            for (int j = 0; j < cols; ++j) {
                int pathlength = 0;
                if (hasPath(board, visited, i, j, word, pathlength)) return true;
            }
        }
        return false;
    }

    bool hasPath(const vector <vector<char>>& board, vector<vector<bool>>& visited, int x, int y, const string& word, int& pathlength) {
        if (word.length() == pathlength) return true;
        bool has_path = false;
        if (
            (x >= 0 && y >= 0 && x < board.size() && y < board[0].size()) &&
            !visited[x][y] && board[x][y] == word[pathlength]
            ) {
            visited[x][y] = true;
            ++pathlength;
            has_path = hasPath(board, visited, x - 1, y, word, pathlength) ||
                hasPath(board, visited, x + 1, y, word, pathlength) ||
                hasPath(board, visited, x, y - 1, word, pathlength) ||
                hasPath(board, visited, x, y + 1, word, pathlength);
            if (!has_path) {
                visited[x][y] = false;
                --pathlength;
            }
        }
        return has_path;
    }
};

运行结果 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值