第12题:矩阵中的路径

 题目描述

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

 

考点:回溯法

回溯法一般与递归深度优先遍历联合使用,他的核心就是不断尝试路线,倘若碰壁(走不通)则返回到上一步进行从新试探,其程序结构分为两部分: 
(1)寻找起点,并在起点位置调用探索函数。 
(2)设计递归探索函数,每一种可能都是一种if,其约束条件就是 探索是否超越边界and 探索位置的值是否是所需

(1)适用范围:需要找出全部解或者最优解 
(2)有组织的搜索 
(3)探索解空间树

 

 

思路

1.bool型hasPath函数,参数:矩阵字符串const char*,矩阵行数int ,矩阵列数int,路径字符串const char*,返回值bool

1.1如果矩阵为空,或者路径为空,则返回false
1.2从路径第一个字符开始

1.3动态分配一个bool矩阵标记是否访问过这个格子并初始化。
1.4从矩阵的任意位置作为起点开始搜索
        1.4.1如果搜索函数为真,则返回真             
1.5释放bool矩阵
1.6返回默认值false
  

2.bool型递归搜索函数,参数:矩阵字符串const char*,第row行int,第col列int,矩阵行数int,矩阵列数int,路径字符串const char*,访问矩阵数组bool*。

2.1 如果到达了路径最末尾,就返回真。

2.2 定义一个bool变量,标志该位置的上下左右是否存在一个字符满足路径下一个字符,并初始化为false

2.3判断范围:1.数组越界row<rows,row>=0;2.值相等;3.未曾访问

2.3.1 假设这个路径可以通过,路径++

2.3.2 更新访问矩阵

2.3.3更新hasPath,访问上下左右,调用递归函数,

2.3.4检查hasPath,如果没有符合到达终点的路径,就返回上个路径,并更新访问矩阵

2.4 搜索函数返回hasPath的值,默认是false,如果到达路径终点,就可以在前面的if中跳出。

 

 

代码

class Solution {
public:

    //bool型hasPath函数,参数:矩阵字符串const char*,矩阵行数int ,矩阵列数int,路径字符串const char*,返回值bool
    bool hasPath(const char* matrix,int rows,int cols,const char* str)
    {
        //如果矩阵为空,或者路径为空,则返回false
        if(matrix==nullptr||rows<1||cols<1||str==nullptr)
            return false;
        
        //从路径第一个字符开始
        int pathLength=0;
            
        //动态分配一个bool矩阵标记是否访问过这个格子并初始化。
        bool* visited=new bool[rows*cols];
        memset(visited,0,rows*cols);
        
        //从矩阵的任意位置作为起点开始搜索
        for(int row=0;row<rows;row++)
        {
            for(int col=0;col<cols;col++)
            {
                if(hasPathCore(matrix,row,col,rows,cols,str,visited,pathLength))//如果搜索函数为真,则返回真
                    return true;
            }
        }
          delete[] visited;//释放bool矩阵
          return false;
    }

  

    //bool型递归搜索函数,参数:矩阵字符串const char*,第row行int,第col列int,矩阵行数int,矩阵列数int,
                            //路径字符串const char*,访问矩阵数组bool*,
    bool hasPathCore(const char* matrix,int row,int col,int rows,int cols,
                     const char* str,bool* visited,int& pathLength)
    {
        if(str[pathLength]=='\0')
            return true;//如果到达了路径最末尾,就返回真。
        
        bool hasPath=false;//定义一个bool变量,标志该位置的上下左右是否存在一个字符满足路径下一个字符,并初始化为false
        
        //判断范围
       //1.数组越界row<rows,row>=0
        //2.值相等
        //3.未曾访问
        if(row<rows&&col<cols&&col>=0&&row>=0&&str[pathLength]==matrix[cols*row+col]&&!visited[cols*row+col])
        {
            //假设这个路径可以通过,路径++
            pathLength++;
            //更新访问矩阵
            visited[row*cols+col]=true;
            
            //更新hasPath,访问上下左右,调用递归函数,
            hasPath=hasPathCore(matrix,row-1,col,rows,cols,str,visited,pathLength)||//上
                hasPathCore(matrix,row+1,col,rows,cols,str,visited,pathLength)||//下
                hasPathCore(matrix,row,col-1,rows,cols,str,visited,pathLength)||//左
                hasPathCore(matrix,row,col+1,rows,cols,str,visited,pathLength);//右
            
            //检查hasPath,如果没有符合到达终点的路径,就返回上个路径,并更新访问矩阵
            if(!hasPath)
            {
                pathLength--;
                visited[cols*row+col]=false;
            }
            
        }
        
        //搜索函数返回hasPath的值,默认是false,如果到达路径终点,就可以在前面的if中跳出。
        return hasPath;
    }
};

核心伪代码 

方法1 使用函数内调用,则计算count需要 global 变量

def f(self,参数):
    "需要内容的布局"

    def f1(参数):
        "需要的比较复杂的条件"

    def f2(参数):
        if "跳出条件1":
            retrun
        if "跳出条件2":
            retrun

        "四个方向的探索"
        f2(r+1,c)
        f2(r-1,c)
        f2(r,c+1)
        f2(r,c-1)

    return '结果' 

 

方法二:采用函数外,就是类下不同方法之间的调用。 
不需要全局

class Solution():
    def Path(self,参数):
        "函数布局,产生随机矩阵,"
        # 调用同类下方法,返回所需值
        self.Find_path(参数)
        # 对所需值进行再处理
        return 结果

    def PD_K(self,参数):
    "将复杂约束条件设定"

    def Find_path(self,参数):
        "对四个位置进行探索,并对所走路径填1"
        对起始位置[0][0]设置为1
        # 如果采用方法之间的调用,则需要将将约束条件融合
        if j+1<n and self.PD_K(参数) and 标记位:
          对走过位置标记
            return self.Find_path(参数)
        elif 四个位置讨论
        else:
            return 所需结果 

 

posted @ 2019-01-31 22:50 lightmare 阅读(...) 评论(...) 编辑 收藏