矩阵中的路径(C++中等区)

矩阵中的路径

题目:请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一格开始,每一步可以在矩阵中向左、右、上、下移动一格。如果一条路径经过了矩阵的某一格,那么该路径不能再次进入该格子。例如,在下面的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


解题思路

题目中说到移动路径可以是上下左右不限方向,只是不能回走到已经走过的路径,那么我们会联想到利用回溯法来解决这道题。回溯法非常适合解决由多个步骤组成的问题,而且每个步骤都有多个选项。回溯法一般用递归来实现。
回溯算法实际上一个类似枚举的搜索尝试过程,主要是在搜索尝试过程中寻找问题的解,当发现已不满足求解条件时,就“回溯”返回,尝试别的路径。回溯法是一种选优搜索法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为“回溯点”。许多复杂的,规模较大的问题都可以使用回溯法,有“通用解题方法”的美称。
回溯算法实际上一个类似枚举的搜索尝试过程,也就是一个个去试,我们解这道题也是通过一个个去试,遍历过程如下图所示:
在这里插入图片描述

这题我们只需将遍历走过的元素替换成‘\0’(字符串中不存在的值),这样就能很好的结合回溯法来满足题目要求了。
在这里插入图片描述
代码执行大致过程如下
首先在board数组中找到一个位置,使得board[i][j] == word[0],可以作为搜索的入口。由于题目说明遍历过的元素不能重复访问,因此我们只需将遍历走过的元素替换成‘\0’(字符串中不存在的值)。然后通过上下左右搜索直到找到一个可行解即返回true,再继续进行下一元素的匹配搜索。若上下左右都没有元素与字符串字符匹配,那么就返回false,代表搜索失败。如果匹配到字符串末尾全部匹配上,则返回true,代表路径搜索成功。


代码展示

代码如下:

class Solution {
public:
    bool exist(vector<vector<char>>& board, string word) {
        if(word.empty()||board.empty()||board[0].empty())
            return false;
        for(int i=0;i<board.size();i++)
        {
            for(int j=0;j<board[0].size();j++)
            {
                //回溯法
                if(dfs(board,word,i,j,0))
                return true;
            }
        }
        return false;
    }
private:
    bool dfs(vector<vector<char>>& board,string& word,int i,int j,int w)
    {
        //判断索引是否越界或者当前值是否匹配,如果不满足则返回false
        if(i<0||i>=board.size()||j<0||j>=board[0].size()||board[i][j]!=word[w])
            return false;
        //如果当前已经匹配到了字符串最后一位,则返回true。(-1是因为数组下标从0开始)
        if(w==word.size()-1)
            return true;

        //保留当前的值到临时变量中
        char tem=board[i][j];
        //将当前值替换成数组中不可能存在的值(目的就是为了让这个值不再被遍历)
        board[i][j]='\0';

        //遍历当前索引的左右下上的值是否与字符串下一字符匹配(递归)
        //若匹配一致则返回true,再继续进行下一字符的判断
        if(dfs(board,word,i-1,j,w+1)
         ||dfs(board,word,i+1,j,w+1)
         ||dfs(board,word,i,j-1,w+1)
         ||dfs(board,word,i,j+1,w+1))
         return true;
        else
        {
            //如果不匹配则将当前值替换为原先值,返回false
            board[i][j]=tem;
            return false;
        }
    }
};
执行用时:24 ms, 在所有 C++ 提交中击败了96.00%的用户
内存消耗:7.7 MB, 在所有 C++ 提交中击败了86.01%的用户

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
邻接矩阵求最短路径算法通常使用 Dijkstra 算法或 Floyd 算法。 1. Dijkstra 算法 Dijkstra 算法是一种单源最短路径算法,其基本思想是从源节点开始,不断扩展最短路径,直到到达目标节点为止。具体步骤如下: (1)初始化:将源节点 s 到所有节点的距离初始化为无穷大,将源节点 s 到自身的距离初始化为 0。 (2)遍历:从源节点 s 开始,按照距离从小到大的顺序遍历所有节点,并更新它们到源节点 s 的距离。 (3)更新:对于当前节点 u 的所有邻居节点 v,如果 u 到源节点 s 的距离加上 u 到 v 的距离小于当前已知的 v 到源节点 s 的距离,则更新 v 的距离。 (4)重复:重复步骤(2)和(3)直到遍历完所有节点或者找到目标节点。 C++ 代码实现: ```c++ const int INF = 0x3f3f3f3f; // 无穷大 int n; // 节点数 int G[MAX][MAX]; // 邻接矩阵 int d[MAX]; // s 到各点的距离 bool vis[MAX]; // 标记是否已确定最短距离 void Dijkstra(int s) { memset(vis, 0, sizeof(vis)); fill(d, d + n, INF); d[s] = 0; for (int i = 0; i < n; i++) { int u = -1; for (int j = 0; j < n; j++) { if (!vis[j] && (u == -1 || d[j] < d[u])) { u = j; } } vis[u] = true; for (int v = 0; v < n; v++) { if (!vis[v] && G[u][v] != INF && d[u] + G[u][v] < d[v]) { d[v] = d[u] + G[u][v]; } } } } ``` 2. Floyd 算法 Floyd 算法是一种多源最短路径算法,其基本思想是通过间节点的遍历,不断缩小节点间的距离,直到得到最终的最短路径。具体步骤如下: (1)初始化:将邻接矩阵 G 初始化为节点间的距离。 (2)遍历:从节点 i 到节点 j 的最短路径可能经过节点 k,因此遍历所有可能的 k 值,更新 i 到 j 的最短路径C++ 代码实现: ```c++ const int INF = 0x3f3f3f3f; // 无穷大 int n; // 节点数 int G[MAX][MAX]; // 邻接矩阵 void Floyd() { for (int k = 0; k < n; k++) { for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { G[i][j] = min(G[i][j], G[i][k] + G[k][j]); } } } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值