学习历程-矩阵中的路径

题目

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

思路

遍历整个数组,找到开头,然后对这个开头进行匹配查找,
对当前已经匹配了的点,需要查看其四个方向,哪个方向 既没有走过,而且匹配下一个字符,有过有就向这个方向前进一步,如果都没有就后退一步,让之前的点继续四个方向中剩下的方向进行判断,
这个是一个递归过程
return条件为

  1. 匹配完成了,这是表示匹配成功,返回成功
  2. 四个方向 都匹配失败了,表示这个点不通,返回失败,只要有一个成功,返回成功

递归入口
每个方向上,如果这个方向没走过、在矩阵内、和要匹配的下个字符相等,就将这个方向的点作为起点进行下一次递归
匹配完成了

class Solution {
public:

    int strlen = 0;//被匹配的字符串长度
    char* path;//临时储存途经的路径
    int rows, cols;//行列长度

	//martix 源数组(二维),str 模式串, beginr、beginc 当前所在row、col,e 当前这步所对应str中的下标
    bool have(char* matrix, char* str, int beginr, int beginc,int e)//递归式
    {
        //printf("e=%d %2d %2d\n", e, beginr, beginc);
        path[beginr * cols + beginc] = e+1;//标记这步为走过。可以标记为1等常数,e+1
        bool is1 = false;//记录向上走是否成狗
        bool is2 = false;//右
        bool is3 = false;//下
        bool is4 = false;//左
        if (e + 1 == strlen)//如果str匹配完毕,返回成功
        {
            return true;
        }
        if (beginr > 0 && path[beginr * cols - cols + beginc] == 0 && str[e + 1] == matrix[beginr * cols - cols + beginc])//如果能够向上走
        {
            is1 = have(matrix, str, beginr - 1, beginc, e + 1);//记录向上是否成功
        }
        if (beginc < cols - 1 && path[beginr * cols + beginc + 1] == 0 && str[e + 1] == matrix[beginr * cols + beginc + 1])//右
        {
            is2 = have(matrix, str, beginr , beginc + 1, e + 1);
        }
        if (beginr < rows - 1 && path[beginr * cols + cols + beginc] == 0 && str[e + 1] == matrix[beginr * cols + cols + beginc])//下
        {
            is3 = have(matrix, str, beginr+1, beginc, e + 1);
        }
        if (beginc > 0 && path[beginr * cols + beginc - 1] == 0 && str[e + 1] == matrix[beginr * cols + beginc - 1])//左
        {
            is4 = have(matrix, str, beginr, beginc - 1, e + 1);
        }
        path[beginr * cols + beginc] = 0;//无论成功失败,这个递归完毕了表示这个点四个方向都走完了,可以交给上一个递归式继续下一个点了,但是这个点可能会在将来被途经到,所有要归零,表示其没走过
        return is4 || is3 || is2 || is1;//四个方向只要有一个成功,那就是成功了
    }
    bool hasPath(char* matrix, int rows, int cols, char* str)//入口
    {
        path = (char*)malloc(sizeof(char) * rows * cols);//新建一个临时储存流经数组
        
        this->rows = rows;
        this->cols = cols;
        this->strlen = std::strlen(str);
        //遍历所有点
        for (int i1 = 0; i1 < rows; i1++)
        {
            for (int i2 = 0; i2 < cols; i2++)
            {
                if (matrix[i1 * cols + i2] == str[0])//如果有一个点和模式串开头匹配,就对其递归,看看这个点能不能成功
                {
                    memset(path, 0, sizeof(char) * rows * cols);//每次递归开始前,清空路径
                    if (have(matrix, str, i1, i2,0))
                    {
                        return true;
                    }
                }
            }
        }
        free(path);

        return false;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值