(剑指offer)回溯法之矩阵中的路径

(剑指offer)回溯法之矩阵中的路径

题目描述:

设计一个函数,用来判断在一个矩阵中是否存在包含某个字符串所有字符串的路径。路径可以从矩阵的任意一格开始,每一步可以在矩阵中向左,右,下移动任意一格。如果一条路径经过了矩阵的某一格,那么该路径不能再次进入该格子。

这是一个可以用回溯法解决的经典题。首先,在矩阵中任选一个格子作为路径的起点。假设矩阵中某个格子的字符为ch,并且这个格子将对应于路径上的第i个字符。如果路径上的第i字符不是ch,那么这个格子不可能处在路径上的第i个位置。如果路径上的第i个字符正好为ch,那么到相邻的格子寻找路径上的第i+1个字符。除矩阵边界上的格子之外,其他格子有4个相邻的格子。重复这个过程,直到路径上的所有字符都在矩阵中找到了相应的位置。

eg:

在这里插入图片描述
按步骤解析上述案例如下:

分析用回湖法解决问题的过程。由于矩阵的第一行第二个字母‘b’和路径"bfce"的第一个字符相等,我们就从这里开始分析。根据题目的要求,我们此时有 3个选项,分别是向左到达字母’a’向右到达字母’t’,向下到达字母’f’。我们先尝试选项’a’,由于此时不可能得到路径"bfce",因此不得不回到节点b尝试下一个选项t。同样,经过节点’t’也不可能得到路径"bfce"‘,因此再次回到节点’b’,尝试下一个选项f。
在节点甲我们也有3个选项,向左、向右都能到达字母’c’、向下到达字母’d’。我们先选择向左到达字母’c’,此时只有一个选择,即向下到达字母’j’。由于此时的路径为"bfcj",不满足题目的约束条件,我们只好回到上一个节点左边的节点’c’。注意到左边的节点’c’的所有选项都己经尝试过,因此只好再回溯到上一个节点’f’并尝试它的下一个选项,即向右到达节点’c’。
在右边的节点’c’我们有两个选择,即向右到达节点’s’,或者向下到达节点’e’。由于经过节点’s’不可能找到满足条件的路径,我们再选择节点’e’,此时路径上的宇母刚好组成字符串"bfce",满足题目的约束条件,因此我们找到了符合要求的解决方案。

Java代码解决方案:

public class MatrixPath {


    public static void main(String[] args) {
        String matrix="ABTGCFCSJDEH";
        String target="ABFB";
        if(!hasPath(matrix,3,4,target))
        {
            System.out.println("正确的,一针见血的");
        }else{
            System.out.println("错误的");
        }

        matrix="ABTGCFCSJDEH";
        target="BFCE";
        if(hasPath(matrix,3,4,target))
        {
            System.out.println("正确的,一针见血的");
        }else{
            System.out.println("错误的");
        }
    }


    public static boolean hasPath(String matrix,int rows,int cols,String target)
    {
        if(matrix==null||cols<1||rows<1)
        {
            return false;
        }

        boolean visited[]=new boolean[rows*cols];
        for(int i=0;i<rows*cols;i++)
        {
            visited[i]=false;
        }

        for(int i=0;i<rows;i++)
        {
            for(int j=0;j<cols;j++)
            {
                if(hasPathCore(matrix,rows,cols,i,j,target,0,visited))
                {
                    return true;
                }
            }
        }

        return false;
    }

    public static boolean hasPathCore(String matrix,int rows,int cols,int row,int col,String target,int length,boolean[] visited)
    {
        if(length==target.length())
        {
            return true;
        }

        boolean hasPath=false;

        if(row>=0&&row<rows&&col>=0&&col<cols&&matrix.charAt(cols*row+col)==target.charAt(length)&&!visited[row*cols+col])
        {
            visited[row*cols+col]=true;

            hasPath=hasPathCore(matrix,rows,cols,row,col-1,target,length+1,visited)||hasPathCore(matrix,rows,cols,row,col+1,target,length+1,visited)||
                    hasPathCore(matrix,rows,cols,row+1,col,target,length+1,visited)||hasPathCore(matrix,rows,cols,row-1,col,target,length+1,visited);
            if(!hasPath){
                visited[row*cols+col]=false;
            }

        }

        return hasPath;
    }
}
``
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值