首页 > 试题广场 >

矩阵中的路径

[编程题]矩阵中的路径
  • 热度指数:436950 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 64M,其他语言128M
  • 算法知识视频讲解
请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向上,向下移动一个格子。如果一条路径经过了矩阵中的某一个格子,则该路径不能再进入该格子。 例如 矩阵中包含一条字符串"bcced"的路径,但是矩阵中不包含"abcb"路径,因为字符串的第一个字符b占据了矩阵中的第一行第二个格子之后,路径不能再次进入该格子。
示例1

输入

"ABCESFCSADEE",3,4,"ABCCED"

输出

true
示例2

输入

"ABCESFCSADEE",3,4,"ABCB"

输出

false
推荐
分析:回溯算法
 这是一个可以用回朔法解决的典型题。首先,在矩阵中任选一个格子作为路径的起点。如果路径上的第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个相邻的格子都没有匹配字符串中下一个的字符,表明当前路径字符串中字符在矩阵中的定位不正确,我们需要回到前一个,然后重新定位。 
  一直重复这个过程,直到路径字符串上所有字符都在矩阵中找到合适的位置
class Solution {
public:
    bool hasPath(char* matrix, int rows, int cols, char* str)
    {   
      if(str==NULL||rows<=0||cols<=0)
           return false;
      bool *isOk=new bool[rows*cols]();
      for(int i=0;i<rows;i++)
      {
           for(int j=0;j<cols;j++)
                if(isHsaPath(matrix,rows,cols,str,isOk,i,j))
                   return true;
      }
      return false;
    }
 bool isHsaPath(char *matrix,int rows,int cols,char *str,bool *isOk,int curx,int cury)
 {
      if(*str=='\0')
           return true;
      if(cury==cols)
      {
           curx++;
           cury=0;
      }
      if(cury==-1)
      {
           curx--;
           cury=cols-1;
      }
      if(curx<0||curx>=rows)
           return false;
      if(isOk[curx*cols+cury]||*str!=matrix[curx*cols+cury])
           return false;
      isOk[curx*cols+cury]=true;
      bool sign=isHsaPath(matrix,rows,cols,str+1,isOk,curx-1,cury)
       ||isHsaPath(matrix,rows,cols,str+1,isOk,curx+1,cury)
       ||isHsaPath(matrix,rows,cols,str+1,isOk,curx,cury-1)
       ||isHsaPath(matrix,rows,cols,str+1,isOk,curx,cury+1);
      isOk[curx*cols+cury]=false;
      return sign;
 }
};

编辑于 2015-09-02 15:01:48 回复(45)
function hasPath(matrix, rows, cols, path)
{
  if (path.length > matrix.length)
    return false;
  if (path.length == 0)
    return true;
  //将matrix化为数组
  matrix = matrix.split('');
  var bitArr = [];
  while (matrix.length > rows) {
    bitArr = matrix.splice(0, cols)
    matrix.push(bitArr);
  }
  //console.log(matrix);

  for (var i = 0; i < rows; i++) {
    var j = matrix[i].indexOf(path[0]); //一行之内可能有多个该字母
    if (j == -1)
      continue;
    else
      for (var k = j; k < cols; k++)
        if (findChar(i, k, 0))
          return true
  }
  return false;
  function findChar(i, j, index) {
    if (index == path.length) //已经超出path长度
      return true;
    if (i < 0 || j < 0 || i == rows || j == cols ||matrix[i][j] == -1) //该值被用过,或者该值过界,则false
    //先判断是否过界
      return false;
    if (matrix[i][j] != path[index])
      return false;
    else (matrix[i][j] == path[index]) //当前位置的值 == path位置字符
    {
      //console.log(matrix[i][j])
     matrix[i][j] = -1;
     if (findChar(i+1, j, index+1) || findChar(i-1, j, index+1)
          || findChar(i, j+1, index+1) || findChar(i, j-1, index+1))
       return true;
     else
     {
       matrix[i][j] = path[index];
       return false;
     }
    }
  }
}


发表于 2020-07-17 08:42:26 回复(0)
function hasPath(matrix, rows, cols, path)
{
    // write code here
    if(!matrix||!path.length||rows <= 0||cols <= 0||rows*cols <path.length){
        return false
    }
    for(var i = 0;i < rows; i++){
       for(var j = 0; j < cols;j++){
            if(dfs(matrix,rows,cols,path,0,[],i,j)){
                return true
            }
        }
    }
    return false
}
function dfs(matrix,rows,cols,path,k,flag,i,j){
    var index = i*cols + j
    if(i < 0||j< 0||matrix[index] != path[k]||flag[index]===true||i >= rows || j >= cols){
        return false
    }
    if(path.length-1 === k){
        return true
    }
    flag[index] = true
    if(dfs(matrix,rows,cols,path,k+1,flag,i-1,j)||
       dfs(matrix,rows,cols,path,k+1,flag,i+1,j)||
       dfs(matrix,rows,cols,path,k+1,flag,i,j-1)||
       dfs(matrix,rows,cols,path,k+1,flag,i,j+1)
      ){
       return true
    }
    flag[index] = false
    return false
    
}

基本思路:
0.根据给定数组,初始化一个标志位数组,初始化为false,表示未走过,true表示已经走过,若不能走就设置为true,表示不能走第二次,
1.根据行数和列数,遍历数组,先找到一个与str字符串的第一个元素相匹配的矩阵元素,进入judge
2.根据i和j先确定一维数组的位置,因为给定的matrix是一个一维数组
3.确定递归终止条件:越界,当前找到的矩阵值不等于数组对应位置的值,已经走过的。都直接false,说明这条路不通
4.k表示已符合字符串的中的长度,若k等于path.length,就是待判定的字符串str的索引已经判断到了最后一位,此时说明是匹配成功的
5.下面就是本题的精髓,递归不断地寻找周围四个格子是否符合条件,只要有一个格子符合条件,就继续再找这个符合条件的格子的四周是否存在符合条件的格子,直到k到达末尾或者不满足递归条件或越界就停止。
6.走到这一步,说明本次是不成功的,我们要还原一下标志位数组index处的标志位,进入下一轮的判断。
发表于 2020-07-07 19:34:53 回复(0)
    function hasPath(matrix, rows, cols, path) {
      const flags = new Array(matrix.length).fill(0);

      for (let i = 0; i < rows; i++) {
        for (let j = 0; j < cols; j++) {
          const index = i * cols + j;
          if (matrix[index] === path[0]) { // 为起点开始
            if (hasPathCore(matrix, rows, cols, path, flags, i, j, 0)) return true;
          }
        }
      }
      return false;
    }

    function hasPathCore(matrix, rows, cols, path, flags, i, j, k) {
      let index = i * cols + j;

      if (i < 0 || j < 0 || i >= rows || j >= cols || flags[index] || path[k] !== matrix[index]) {
        return false;
      }

      if (path.length - 1 === k) {
        return true;
      }

      flags[index] = 1;

      if (hasPathCore(matrix, rows, cols, path, flags, i - 1, j, k + 1) ||
        hasPathCore(matrix, rows, cols, path, flags, i + 1, j, k + 1) ||
        hasPathCore(matrix, rows, cols, path, flags, i, j - 1, k + 1) ||
        hasPathCore(matrix, rows, cols, path, flags, i, j + 1, k + 1)
      ) {
        return true;
      }

      flags[index] = 0;

      return false;
    }

发表于 2019-10-29 20:33:08 回复(0)
回溯算法 问题由多个步骤组成,并且每个步骤都有多个选项。
依次验证path中的每个字符(多个步骤),每个字符可能出现在多个方向(多个选项)
1.根据给定的行列,遍历字符,根据行列数计算出字符位置
2.判断当前字符是否满足递归终止条件
3.递归终止条件:1.行列越界 2.与路径不匹配 3.已经走过(需设定一个数组标识当前字符是否走过)
4.若路径中的字符最后一位匹配成功,则到达边界且满足约束条件,找到合适的解
5.递归不断寻找四个方向是否满足条件,满足条件再忘更深层递归,不满足向上回溯
6.如果回溯到最外层,则当前字符匹配失败,将当前字符标记为未走

    function hasPath(matrix, rows, cols, path) {
      const flag = new Array(matrix.length).fill(false);
      for (let i = 0; i < rows; i++) {
        for (let j = 0; j < cols; j++) {
          if (hasPathCore(matrix, i, j, rows, cols, path, flag, 0)) {
            return true;
          }
        }
      }
      return false;
    }

    function hasPathCore(matrix, i, j, rows, cols, path, flag, k) {
      const index = i * cols + j;
      if (i < 0 || j < 0 || i >= rows || j >= cols || matrix[index] != path[k] || flag[index]) {
        return false;
      }
      if (k === path.length - 1) {
        return true;
      }
      flag[index] = true;
      if (hasPathCore(matrix, i + 1, j, rows, cols, path, flag, k + 1) ||
        hasPathCore(matrix, i - 1, j, rows, cols, path, flag, k + 1) ||
        hasPathCore(matrix, i, j + 1, rows, cols, path, flag, k + 1) ||
        hasPathCore(matrix, i, j - 1, rows, cols, path, flag, k + 1)) {
        return true;
      }
      flag[index] = false;
      return false;
    }

发表于 2019-04-11 20:39:14 回复(0)

输入的矩阵是字符串,我佛了

function hasPath(matrix, rows, cols, path)
{
    // write code here
    var parr=matrix.split('');
    var y=[];
    for(var i=0;i<rows;i++){
        var yy=[];
        for(var ii=0;ii<cols;ii++){
            yy.push(parr.shift());
        }
        y.push(yy);
    }
    matrix=y;
    function cp(arr){
        var result=[];
        for(var i=0;i<arr.length;i++){
            let a=[...arr[i]];
            result.push(a);
        }
        return result;
    }

    if(matrix.length===0||matrix[0].length===0)
        return false;
    var find=function(arr,patharr,x,y){
        if(patharr.length===0)
            return true;
        if(x<0||y<0||x>arr.length-1||y>arr[0].length-1)
            return false;

        if(arr[x][y]!==patharr[0])
            return false;
        let copy=cp(arr);
        copy[x][y]=0;
        let copypath=[...patharr];
        copypath.shift();
        if(copypath.length===0)
            return true;
        if(find(copy,copypath,x-1,y))
            return true;
        if(find(copy,copypath,x+1,y))
            return true;
        if(find(copy,copypath,x,y-1))
            return true;
        if(find(copy,copypath,x,y+1))
            return true;
        return false;
    }
    for(var i=0;i<matrix.length;i++){
        for(var ii=0;ii<matrix[0].length;ii++){

            if(matrix[i][ii]==path[0]){
                // console.log(i,ii);
                if(find(matrix,path.split(''),i,ii)==true){
                    return true;
                }
            }
        }
    }
    return false;
}
编辑于 2019-04-01 20:29:09 回复(0)
 function hasPath(matrix, rows, cols, path)
{ // write code here  var visit = new Array(rows), pathLength = 0; for(var i = 0; i < visit.length; i++){ visit[i] = Array(cols).fill(false);
    } function hasPathCore (row,col) { var isHasPath = false; if(pathLength === path.length - 1){ return true;
        } console.log(matrix[row * cols + col] === path[pathLength]); if(row >=0 && row < rows && col >=0 && col < cols && matrix[row * cols + col] === path[pathLength] && !visit[row][col]){ pathLength++; visit[row][col] = true; isHasPath = hasPathCore(row - 1,col) || hasPathCore(row + 1,col) || hasPathCore(row ,col + 1) || hasPathCore(row ,col - 1); if(!isHasPath){ visit[row][col]= false; pathLength--;
            }
        } return isHasPath;
    } for( i = 0; i < rows; i++){ for(var j = 0; j < cols; j++){ if(hasPathCore(i,j)){ return true;
            }
        }
    } return false;
}
用例"ABCESFCSADEE",3,4,"SEE"
牛客说错了我输出false,我同一段代码复制到浏览器,结果是true。。
发表于 2017-09-12 15:03:22 回复(1)