三、矩阵中的路径

本文介绍了一种用于判断矩阵中是否存在特定字符串路径的DFS算法。通过递归方式,从矩阵任一点出发,寻找与字符串匹配的路径,确保路径不重复经过同一格子。详细解析了递归函数的设计思路与代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、题目描述

请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向上,向下移动一个格子。如果一条路径经过了矩阵中的某一个格子,则该路径不能再进入该格子。 例如  矩阵中包含一条字符串"bcced"的路径,但是矩阵中不包含"abcb"路径,因为字符串的第一个字符b占据了矩阵中的第一行第二个格子之后,路径不能再次进入该格子

二、解析

这是我看过一个人的解析思路,我觉得是不错的。

首先分析一下这是一道dfs的题目,我们可以先找到字符串第一个字符在矩阵中有没有匹配,再在他的上下左右去找第二个,同样思路去找第三个直到字符串匹配完。

这里就要用到递归了,递归函数就是当前处理的问题是什么,并且下一次在规模减小的情况下处理相同的问题。比如此题:当前处理的问题是:判断字符串str[0 ... len]是否在mat中匹配,显然下一次递归处理的问题是:如果str[0]已经匹配,则判断字符串str[1 ... len]是否在mat中匹配。

递归函数要怎么写呢?

dfs(){
 
    // 第一步,检查下标是否满足条件
 
    // 第二步:检查是否被访问过,或者是否满足当前匹配条件
 
    // 第三步:检查是否匹配当前字符串的字符
 
    // 第四步:上面没有返回,说明当前矩阵的字符匹配字符串要匹配的字符,对其做标记,然后匹配下一个
    
    // 第五步:上下左右匹配下个字符,使用循环
    dfs(下一次)
    
    // 第六步:如果上下左右都没有匹配,将此时已经标记的矩阵字符修改回去(回溯)
} 

思考dfs参数,因为一次递归是要匹配一个字符,所以要确定矩阵的某个字符,以及字符串的某个字符,矩阵靠行列确定,字符串靠具体到那一个字符确定,也就是说要给一个整数表示当前匹配到哪个字符

//i,j表示矩阵位置,pos表示匹配字符串第几个,一次dfs匹配一个字符
    bool dfs(int i,int j,int pos,char * str)

三、代码实现

class Solution {
public:
    int h;//表示行数
    int w;//表示列数
    char * mar;//矩阵
    int str_len;//字符串长度
    int d[5]={-1,0,1,0,-1};//上下左右移动时用到
    bool hasPath(char* matrix, int rows, int cols, char* str)
    {
        h=rows;
        w=cols;
        mar=matrix;
        str_len=strlen(str);
        for(int i=0;i<rows;i++){
            for(int j=0;j<cols;j++){
                //循环匹配第一个字符
                if(dfs(i,j,0,str))
                    return true;
            }
        }
        return false;
    }
    
    //i,j表示矩阵位置,pos表示匹配字符串第几个,一次dfs匹配一个字符
    bool dfs(int i,int j,int pos,char * str){
        //超出边界
        if(i<0||i>=h||j<0||j>=w)
            return false;
        
        char ch = mar[i*w+j];
        //#为已经标记了,已经标记或不等于返回false
        if(ch=='#'||ch!=str[pos])
            return false;
        
        //字符串全部匹配完
        if(pos+1==str_len)
            return true;
        
        //当前字符匹配成功进行标记
        mar[i*w+j]='#';
        
        //上下左右移动匹配下个字符
        for(int l=0;l<4;l++){
            if(dfs(i+d[l],j+d[l+1],pos+1,str))
                return true;
        }
        
        //上下左右匹配下个字符不成功,将矩形的#标记重新改回原来的字符
        mar[i*w+j]=ch;
        return false;
    }


};

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值