剑指 Offer 12 - 矩阵中的路径(Leetcode 79)

1 题目

https://leetcode-cn.com/problems/ju-zhen-zhong-de-lu-jing-lcof/

2 题意

请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一格开始,每一步可以在矩阵中向左、右、上、下移动一格。如果一条路径经过了矩阵的某一格,那么该路径不能再次进入该格子。例如,在下面的3×4的矩阵中包含一条字符串“bfce”的路径(路径中的字母用加粗标出)。

[["a","b","c","e"],
["s","f","c","s"],
["a","d","e","e"]]

但矩阵中不包含字符串“abfb”的路径,因为字符串的第一个字符b占据了矩阵中的第一行第二个格子之后,路径不能再次进入这个格子。

示例 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

3 思路

author's blog == http://www.cnblogs.com/toulanboy/

本题要求判断图中是否存在一条指定的路径。求起点到终点的问题,我们可以借助深度优先搜索解决。

具体方案为:
先找出第0个字符在矩阵中出现的位置,然后基于这个位置判断四周是否存在第1个字符。然后再基于第1个字符判断四周是否存在第2个字符,以此类推,直到找到第n个字符。

可以发现上述过程实际上都是由相同的子过程组成,只是这些子过程的参数不一样。所以,我们只需写一个函数,负责判断第i个位置附近是否有第i+1字符,然后递归调用即可。

4 代码

//author's blog == http://www.cnblogs.com/toulanboy/
class Solution {
public:
    int direction[4][2] = {{0, 1}, {0, -1}, {-1, 0}, {1, 0}};//方向偏移量
    bool visit[201][201];//访问标志,避免重复使用同一位置的字符
    //dfs(): 判断(x, y)周围是否有word[pos]。
    bool dfs(int x, int y, int pos, vector<vector<char>>& board, string& word){
        if(pos >= word.size()){
            return true;
        }
        int n = board.size();
        int m = board[0].size();
        for(int i=0; i<4; ++i){//4个方向
            int new_x = x + direction[i][0];
            int new_y = y + direction[i][1];
            //合法性判断
            if(new_x >= 0 && new_x < n && new_y >=0 && new_y < m && visit[new_x][new_y]==false){
                if(board[new_x][new_y] == word[pos]){//如果(x, y)周围是否有word[pos],
                    visit[new_x][new_y] = true;
                    if(dfs(new_x, new_y, pos+1, board, word)){//那么判断(new_x, new_y)周围是否有word[pos+1]
                        return true;
                    }
                    visit[new_x][new_y] = false;
                }
            }
        }
        return false;
    }

    bool exist(vector<vector<char>>& board, string word) {
        memset(visit, 0, sizeof(visit));
        //先找到第0个字符在矩阵中出现位置,然后基于这个位置找下一位数字
        for(int i=0; i<board.size(); ++i){
            for(int j=0; j<board[i].size(); ++j){
                if(board[i][j] == word[0]){//如果(i, j)出现了word[0]
                    visit[i][j] = true;
                    if(dfs(i, j, 1, board, word)){//判断(i, j)周围是否有word[1]
                        return true;
                    }
                    visit[i][j] = false;
                }
            }
        }
        return false;
    }
};
posted @ 2020-09-20 22:12  偷懒人  阅读(106)  评论(0编辑  收藏  举报