zoukankan      html  css  js  c++  java
  • 剑指offer-矩阵中的路径

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

    例如下面的矩阵包含了一条 bfce 路径。(因为题目中的矩阵是用一维数组来表示二维数组的)

    链接:https://www.nowcoder.com/questionTerminal/c61c6999eecb4b8f88a98f66b273a3cc
    来源:牛客网

    分析:回溯算法
     这是一个可以用回朔法解决的典型题。首先,在矩阵中任选一个格子作为路径的起点。如果路径上的第i个字符不是ch,那么这个格子不可能处在路径上的
    第i个位置。如果路径上的第i个字符正好是ch,那么往相邻的格子寻找路径上的第i+1个字符。除在矩阵边界上的格子之外,其他格子都有4个相邻的格子。
    重复这个过程直到路径上的所有字符都在矩阵中找到相应的位置。
      由于回朔法的递归特性,路径可以被开成一个栈。当在矩阵中定位了路径中前n个字符的位置之后,在与第n个字符对应的格子的周围都没有找到第n+1个
    字符,这个时候只要在路径上回到第n-1个字符,重新定位第n个字符。
      由于路径不能重复进入矩阵的格子,还需要定义和字符矩阵大小一样的布尔值矩阵,用来标识路径是否已经进入每个格子。 当矩阵中坐标为(row,col)的
    格子和路径字符串中相应的字符一样时,从4个相邻的格子(row,col-1),(row-1,col),(row,col+1)以及(row+1,col)中去定位路径字符串中下一个字符
    如果4个相邻的格子都没有匹配字符串中下一个的字符,表明当前路径字符串中字符在矩阵中的定位不正确,我们需要回到前一个,然后重新定位。
      一直重复这个过程,直到路径字符串上所有字符都在矩阵中找到合适的位置
    链接:https://www.nowcoder.com/questionTerminal/c61c6999eecb4b8f88a98f66b273a3cc
    来源:牛客网
    
    核心思路:回溯法
    1.先将matrix字符串映射为字符矩阵;
    2.从原字符串中找到第一个跟str[0]相等的字符,得到其对应的在矩阵中的位置[r,c]
    1)从[r,c]开始按 上、左、右、下的顺序搜索;
    2)每当搜索到一个节点,先判断path是否包括它,包括就说明已经经过此节点,不能
    再经过了;如果不包括,就将其加入path容器
    3)直到搜索到str[length - 1]节点,说明成功找到,标记result为true,标记
    isFinished为true,尽快结束所有的递归操作
    4)如果某节点起的 上、左、右、下 都搜索过但还没找到结果,说明经过此节点的路
    径都不满足题意,将其从path中删除,回溯到上一层继续找。
    (PS:确实是回溯法,不过代码有点长,实现的有点繁杂)
    

      

     
    public class Solution {
        private final static int[][] dir = {{0,-1},{0,1},{-1,0},{1,0}};
        private int row, col;
        public boolean hasPath(char[] matrix, int rows, int cols, char[] str)
        {    
             if(row==0 || col==0) return false;
            this.row = row;
            this.col = col;
            boolean[][] flag = new boolean[row][col];
            //char[][] a = build(matrix);
            char a[][] = new char[row][col];
            for(int i=0,k=0; i<row; i++) {
                for(int j=0; j<col; j++) {
                    a[i][j] = matrix[k++];
                }
            }
            for(int i=0; i<row; i++) {
                for(int j=0; j<col; j++) 
                    if(dfs(a,str,flag,0,i,j)) 
                        return true;
            }
            return false;
        }
        private boolean dfs(char[][] a,char[] str,boolean[] flag,int pathLen, int r,int c){
            if(pathLen == str.length) return true;
            if(r<0 || r>=row || c<0 || c>=col || a[r][c] != str[pathLen] || flag[r][c])
                return false;
            flag[r][c] = true;
            for(int[] d:dir) {
                if(dfs(a,str,flag,pathLen+1,r+d[0],c+d[1])) 
                    return true;
        }
            flag[r][c]=false;
            return false;
    }
    链接:https://www.nowcoder.com/questionTerminal/c61c6999eecb4b8f88a98f66b273a3cc
    来源:牛客网
    
        public boolean hasPath(char[] matrix, int rows, int cols, char[] str){
            boolean[] visited = new boolean[matrix.length];
            for (int i = 0; i < rows; i++) {
                for (int j = 0; j < cols; j++) {
                    if (searchFromHere(matrix,rows,cols,i,j,0,str,visited))
                        return true;
                }
            }
    //        System.out.println(Arrays.toString(visited));
            return false;
        }
        public boolean searchFromHere(char[] matrix,int rows,int cols,int r,int c,int index,char[] str,boolean[] visited){
            if (r < 0 || r >= rows || c < 0 || c >= cols || matrix[r * cols + c] != str[index] || visited[r * cols + c])
                return false;
            if (index == str.length - 1)    return true;
            visited[r * cols + c] = true;
            if (searchFromHere(matrix,rows,cols,r - 1,c,index + 1,str,visited) ||
                    searchFromHere(matrix,rows,cols,r,c -1,index + 1,str,visited) ||
                    searchFromHere(matrix,rows,cols,r + 1,c,index + 1,str,visited) ||
                    searchFromHere(matrix,rows,cols,r,c + 1,index + 1,str,visited))
                return true;
            visited[r * cols + c] = false;
            return false;
        }

    链接:https://www.nowcoder.com/questionTerminal/c61c6999eecb4b8f88a98f66b273a3cc
    来源:牛客网

    回溯
    基本思想:
    0.根据给定数组,初始化一个标志位数组,初始化为false,表示未走过,true表示已经走过,不能走第二次
    1.根据行数和列数,遍历数组,先找到一个与str字符串的第一个元素相匹配的矩阵元素,进入judge
    2.根据i和j先确定一维数组的位置,因为给定的matrix是一个一维数组
    3.确定递归终止条件:越界,当前找到的矩阵值不等于数组对应位置的值,已经走过的,这三类情况,都直接false,说明这条路不通
    4.若k,就是待判定的字符串str的索引已经判断到了最后一位,此时说明是匹配成功的
    5.下面就是本题的精髓,递归不断地寻找周围四个格子是否符合条件,只要有一个格子符合条件,就继续再找这个符合条件的格子的四周是否存在符合条件的格子,直到k到达末尾或者不满足递归条件就停止。
    6.走到这一步,说明本次是不成功的,我们要还原一下标志位数组index处的标志位,进入下一轮的判断。
    链接:https://www.nowcoder.com/questionTerminal/c61c6999eecb4b8f88a98f66b273a3cc
    来源:牛客网
    
    public class Solution {
        public boolean hasPath(char[] matrix, int rows, int cols, char[] str)
        {
            //标志位,初始化为false
            boolean[] flag = new boolean[matrix.length];
            for(int i=0;i<rows;i++){
                for(int j=0;j<cols;j++){
                     //循环遍历二维数组,找到起点等于str第一个元素的值,再递归判断四周是否有符合条件的----回溯法
                     if(judge(matrix,i,j,rows,cols,flag,str,0)){
                         return true;
                     }
                }
            }
            return false;
        }
         
        //judge(初始矩阵,索引行坐标i,索引纵坐标j,矩阵行数,矩阵列数,待判断的字符串,字符串索引初始为0即先判断字符串的第一位)
        private boolean judge(char[] matrix,int i,int j,int rows,int cols,boolean[] flag,char[] str,int k){
            //先根据i和j计算匹配的第一个元素转为一维数组的位置
            int index = i*cols+j;
            //递归终止条件
            if(i<0 || j<0 || i>=rows || j>=cols || matrix[index] != str[k] || flag[index] == true)
                return false;
            //若k已经到达str末尾了,说明之前的都已经匹配成功了,直接返回true即可
            if(k == str.length-1)
                return true;
            //要走的第一个位置置为true,表示已经走过了
            flag[index] = true;
             
            //回溯,递归寻找,每次找到了就给k加一,找不到,还原
            if(judge(matrix,i-1,j,rows,cols,flag,str,k+1) ||
               judge(matrix,i+1,j,rows,cols,flag,str,k+1) ||
               judge(matrix,i,j-1,rows,cols,flag,str,k+1) ||
               judge(matrix,i,j+1,rows,cols,flag,str,k+1)  )
            {
                return true;
            }
            //走到这,说明这一条路不通,还原,再试其他的路径
            flag[index] = false;
            return false;
        }
    }
  • 相关阅读:
    vnc安装
    centos下安装图形界面
    granfana telegraf influx安装与使用
    jenkins安装与使用
    yum使用手册
    Python模块--并发相关threading、multiprocessing、Queue、gevent
    Python模块--logging
    Python模块--psutil
    python模块--Beautifulsoup
    Python模块--Pexpect
  • 原文地址:https://www.cnblogs.com/Roni-i/p/10367394.html
Copyright © 2011-2022 走看看