《剑指offer》--012--矩阵中的路径

《剑指offer》–目录索引

题目:

请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有
字符的路径。路径可以从矩阵中任意一格开始,每一步可以在矩阵中向左、右、
上、下移动一格。如果一条路径经过了矩阵的某一格,那么该路径不能再次进入
该格子。例如在下面的3×4的矩阵中包含一条字符串“bfce”的路径(路径中的字
母用下划线标出)。但矩阵中不包含字符串“abfb”的路径,因为字符串的第一个
字符b占据了矩阵中的第一行第二个格子之后,路径不能再次进入这个格子。
A B T G
C F C S
J D E H

思路:

这是一个回溯递归的问题,需要注意以下几点:
①可以从任意一格开始:我们使用二维数组的双重for循环把所有坐标的情况都遍历一遍,代表任意位置开始
②走过的格子不能再走:矩阵用字符二维数组表示,我们可以再建一个动态数组,坐标一一对应,记录每个位置是否被走过的状态
③判断一个位置是否是合格的:如果该位置的字符与字符串中字符对应,再判断该位置的上下左右四个位置中是否能继续找到对应字符,能找到代表合格,则继续递归;不能找到,代表不合格,返回结果,并重新寻找该字符

代码如下:
PathInArray.h

#ifndef __PATHINARRAY_H__
#define __PATHINARRAY_H__

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int HasPathCore(const char* arr,int rows,int cols,int row,int col,const char* str,int* PathLength,int* HasVisited);//判断矩阵中是否存在路径
int HasPath(const char* arr,int rows,int cols,const char* str);//判断矩阵中是否存在路径核心代码

#endif

PathInArray.c

#ifndef __PATHINARRAY_H__
#define __PATHINARRAY_H__

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int HasPathCore(const char* arr,int rows,int cols,int row,int col,const char* str,int* PathLength,int* HasVisited);//判断矩阵中是否存在路径
int HasPath(const char* arr,int rows,int cols,const char* str);//判断矩阵中是否存在路径核心代码

#endif
[wy@localhost 012 矩阵中的路径]$ cat PathInArray.c
#include "PathInArray.h"

int HasPath(const char* arr,int rows,int cols,const char* str)//判断矩阵中是否存在路径
{
    int* HasVisited=(int *)malloc(sizeof(int)*cols*rows);//动态数组,为了对应字符矩阵的每个位置
    memset(HasVisited,0,rows*cols); //全部初始化0,代表每个位置还未被走过

    int PathLength=0;//初始化字符串下标为0
    int i=0,j=0;

    //可以从矩阵的任意位置开始
    for(;i<rows;i++)
        for(;j<cols;j++)
        {
            if(HasPathCore(arr,rows,cols,i,j,str,&PathLength,HasVisited) == 1)
            {
                return 1;//1代表有该路径
            }
        }

    free(HasVisited);
    HasVisited=NULL;
    return 0;//0代表没有该路径
}

int HasPathCore(const char* arr,int rows,int cols,int row,int col,const char* str,int* PathLength,int* HasVisited)//判断矩阵中是否存在路径核心代码
{
    if(str[*PathLength] == '\0')//比较到字符串尾
    {
        return 1;
    }

    if(row < 0 || col < 0 || row >= rows || col >= cols)//越界
    {
        return 0;
    }

    int hasPath=0;//定义一个变量接收一个位置大上下左右四个位置的返回值,用于判断该位置是否是合格位
    if(arr[row*cols+col] == str[*PathLength] && HasVisited[row*cols+col] == 0)//字符相同并且该位置未被走过
    {
        (*PathLength)++;//字符串的下标加一,往下找
        HasVisited[row*cols+col]=1;//标记该位置已被走过
        hasPath=HasPathCore(arr,rows,cols,row-1,col,str,PathLength,HasVisited)
              + HasPathCore(arr,rows,cols,row+1,col,str,PathLength,HasVisited)
              + HasPathCore(arr,rows,cols,row,col-1,str,PathLength,HasVisited)
              + HasPathCore(arr,rows,cols,row,col+1,str,PathLength,HasVisited);

        if(hasPath == 0)//如果该位置的上下左右四个位置在不能找到后续的字符,说明该位置不合该
        {
            (*PathLength)--;//字符串的下标减一,回头再找
            HasVisited[row*cols+col]=0;//取消刚才的标记,为后面有可能再找到该位置做准备
        }
    }   
    else
    {
        return 0;
    }

    return hasPath;
}

test.c

#include "PathInArray.h"

void test()
{
    const char* arr="ABTGCFCSJDEH";
    const char* str1="BFCE";
    const char* str2="BFCB";
    const char* str3="BFCX";
    printf("%d\n",HasPath(arr,3,4,str1));
    printf("%d\n",HasPath(arr,3,4,str2));
    printf("%d\n",HasPath(arr,3,4,str3));
}

int main()
{
    test();
    return 0;
}

运行结果:
这里写图片描述

1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。、可私 6信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 、可私信6博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 、可私信6博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值