第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 所需结果