首页 > 试题广场 >

矩阵中的路径

[编程题]矩阵中的路径
  • 热度指数: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)

思路

毋庸置疑最先想到回溯法
说一个空间复杂度O(1)的。
走过的地块标为 ' ' 等不会用到的字符即可。
时间复杂度最差也不会到O(n2),没时间没能力算具体多少,总之实际上不太多。
类似的问题如:填海造陆,离陆最远等dfs,bfs问题。

多说两句说一下思路吧。数组存储的矩阵的任意一点(i,j)在数组中的位置k=i*cols+j
(btw,k在矩阵一点的位置(k/cols, k%cols))
通过递归回溯,遍历数组,找从一点开始上下左右走且不重复的情况下,走出str路径的情况即可。

代码

    public boolean hasPath(char[] matrix, int rows, int cols, char[] str) {
        for (int i = 0; i < matrix.length; i++) {
            if (findPath(matrix, cols, i, str, 0)) return true;
        }
        return false;
    }

    public boolean findPath(char[] matrix, int cols, int k, char[] str, int c) {
        if (c >= str.length) return true;
        if (k < 0 || k >= matrix.length || matrix[k] != str[c]) return false;
        int i = k / cols;
        int j = k % cols;
        char tmp = matrix[k];
        matrix[k] = ' ';
        if (findPath(matrix, cols, (i-1)*cols+j, str, c+1) ||
        findPath(matrix, cols, (i+1)*cols+j, str, c+1) ||
        findPath(matrix, cols, i*cols+j-1, str, c+1) ||
        findPath(matrix, cols, i*cols+j+1, str, c+1))
            return true;
        matrix[k] = tmp;
        return false;
    }
发表于 2021-02-22 20:46:11 回复(0)
回溯,利用坐标映射无需构造二维数组
public class Solution {
    public boolean hasPath(char[] matrix, int rows, int cols, char[] str)
    {
        for(int i=0;i<matrix.length;i++){
            if(judge(matrix,i,cols,str,0))
                return true;
        }
        return false;
    }
    
    public boolean judge(char[] matrix,int q, int cols, char[] str, int p){
        if(p==str.length)
            return true;
        if(q>=0 && q<matrix.length && matrix[q]==str[p]){
            matrix[q] = '#';
            boolean right = judge(matrix,q+1,cols,str,p+1);
            boolean left = judge(matrix,q-1,cols,str,p+1);
            boolean up = judge(matrix,q-cols,cols,str,p+1);
            boolean down = judge(matrix,q+cols,cols,str,p+1);
            matrix[q] = str[p];
            return right||left||up||down;
        }
        return false;
    }

}

发表于 2021-02-03 15:02:42 回复(0)
public class Solution {
    int w=0,h=0;
    int[] dir = {-1,0,1,0,-1};
    
    public boolean dfs(char[] mat, int x, int y,int pos, char[] str)
    {
        //如果已经占过了就返回false;
        if(x>=h || x<0 || y>=w || y<0)
            return false;
        
        char c = mat[x*w+y];
        if(c=='#' || c!=str[pos])
            return false;
        
        if(pos==str.length-1)
            return true;
        
        mat[x*w+y]='#';
        for(int i=0;i<dir.length-1;++i){

            if(dfs(mat,x+dir[i],y+dir[i+1],pos + 1,str))
                return true;
         }
          mat[x*w+y] = c;
          return false;
        
        
    }
    public boolean hasPath(char[] matrix, int rows, int cols, char[] str)
    {
        
        w = cols;
        h = rows;
        for(int x=0;x<rows;++x){
            for(int y=0;y<cols;++y){
                if(dfs(matrix,x,y,0,str)){
                   return true;
                }
            }
        }
        return false;
    }


}
记住深度优先遍历的递归通时就差不多会做了
还可以记住方向数组的设置。
不用一遍递归出答案,可以判断每次的递归结果,整个图遍历完成时 判断最终的结果。

发表于 2021-01-21 20:22:55 回复(0)
public class Solution {
    private int[][] visited;
    public boolean hasPath(char[] matrix, int rows, int cols, char[] str)
    {
       visited = new int[rows][cols];
		for (int x = 0; x <= rows - 1; x++) {
			for (int y = 0; y <= cols - 1; y++) {
				if (findNext(matrix, rows, cols, x, y, str, 0)) {
					return true;
				}
			}
		}
		return false;
    }
    
    public boolean findNext(char[] matrix, int rows, int cols, int x, int y, char[] str, int k) {
		if (k == str.length) {
			return true;
		}
		if (x < 0 || y < 0 || x >= rows || y >= cols || visited[x][y] == 1) {
			return false;
		}
		if (str[k] != matrix[x * cols + y])
			return false;
		// 当前相同,按顺时针走
		visited[x][y] = 1;
		if (findNext(matrix, rows, cols, x + 1, y, str, k + 1))
			return true;
		if (findNext(matrix, rows, cols, x, y + 1, str, k + 1))
			return true;
		if (findNext(matrix, rows, cols, x - 1, y, str, k + 1))
			return true;
		if (findNext(matrix, rows, cols, x, y - 1, str, k + 1))
			return true;
		visited[x][y] = 0;
		return false;
	}


}

发表于 2021-01-15 22:55:59 回复(0)
public class Solution {
    char[] matrix;
    int rows;
    int cols;
    char[] str;
    int[] visited;
    public boolean hasPath(char[] matrix, int rows, int cols, char[] str)
    {
        if(matrix == null && str != null){
            return false;
        }
        if(str == null){
            return false;
        }
        this.matrix = matrix;
        this.rows = rows;
        this.cols = cols;
        this.str = str;
        // 标识matrix中元素有没有被访问
        visited = new int[matrix.length];
        // 第一行第二个就等于matrix[0*rows+1]
        for(int i = 0; i < rows; i++){
            for(int j = 0; j < cols; j++){
                // 找到matrix中与str第一个字符相等的位置从这里开始
                if(matrix[i*cols+j] == str[0]){
                    boolean result = path(i,j,0);
                    if(result){
                        return true;
                    }
                }
            }
        }
        return false;
    }
    public boolean path(int startRow, int startCol,int index){

        // 如果不相同说明这条路径不通需要回溯,或者这个节点已经走过
        if(matrix[startRow * cols +startCol] != str[index] || visited[startRow * cols +startCol] == 1){
            return false;
        }
        // 标记节点已经访问过
        visited[startRow * cols +startCol] = 1;
        // 说明已经到最后返回true,否则继续走
        if(index+1 >= str.length){
            return true;
        }
        // 向上走
        if(startRow-1 >= 0){
            if(path(startRow-1, startCol, index+1)){
                return true;
            }
        }
        // 向下走
        if(startRow+1 < rows){
            if(path(startRow+1, startCol, index+1)){
                return true;
            }
        }
        // 向左走
        if(startCol-1 >= 0){
            if(path(startRow, startCol-1, index+1)){
                return true;
            }
        }
        // 向右走
         if(startCol+1 < cols){
            if(path(startRow, startCol+1, index+1)){
                return true;
            }
        }
        // 回溯
        visited[startRow * cols +startCol] = 0;
        return false;
    }
}

发表于 2020-12-25 13:17:45 回复(0)
class Solution {
    private final int [][] dir = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
    private boolean result = false;
    private boolean [][] vis;
    private boolean check(int rows, int cols, int nextX, int nextY) {
        return nextX < rows && nextX >= 0 && nextY < cols && nextY >= 0;
    }
    private void dfs(char[][] chs, int rows, int cols, char[] str, int x, int y, int curLen) {
        if (str.length <= curLen) {
            result = true;
            return;
        }
        if (!check(rows, cols, x, y) || vis[x][y] || chs[x][y] != str[curLen]) {
            return;
        }
        vis[x][y] = true;
        for (int i = 0; i < 4; i++) {
            int nextX = x + dir[i][0];
            int nextY = y + dir[i][1];
            dfs(chs, rows, cols, str, nextX, nextY, curLen + 1);
        }
        vis[x][y] = false;
    }
    public boolean hasPath(char[] matrix, int rows, int cols, char[] str) {
        if (matrix.length < str.length) {
            return false;
        }
        char [][] chs = new char[rows][cols];
        vis = new boolean[rows][cols];
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                chs[i][j] = matrix[i*cols + j];
                vis[i][j] = false;
            }
        }
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                dfs(chs, rows, cols, str, i, j, 0);
            }
        }
        return result;
    }
}
http://www.pytap.com/article/1004
发表于 2020-11-18 18:07:33 回复(0)
import java.util.*;

public class Solution {
    public boolean hasPath(char[] matrix, int rows, int cols, char[] str)
    {
        int n = 0;
        List<Integer> list = new ArrayList<>();
        // 找到所有和字符串第一个字母相同的位置
        while (n < matrix.length) {
            if (matrix[n] == str[0]) {
                list.add(n);
            }
            n++;
        }
        
        for (int index : list) {
            Map<Integer, Integer> map = new HashMap<>();
            map.put(index, 0);
            boolean res = scan(matrix, rows, cols, index, str, 1, map);
            if (res) {
                return true;
            }
        }
        return false;
    }

    private boolean scan(char[] matrix, int rows, int cols, int n, char[] str, int k, Map<Integer, Integer> map) {
        if (k == str.length) {
            return true;
        }
        int i = n / cols;
        int j = n % cols;
        // 向上搜索
        if (i > 0 && matrix[n - cols] == str[k] && map.get(n - cols) == null) {
            map.put(n - cols, 0);
            boolean res = scan(matrix, rows, cols, n - cols, str, k + 1, map);
            if (res) {
                return res;
            }
        }
        // 向下搜索
        if (i < rows - 1 && matrix[n + cols] == str[k] && map.get(n + cols) == null) {
            map.put(n + cols, 0);
            boolean res = scan(matrix, rows, cols, n + cols, str, k + 1, map);
            if (res) {
                return res;
            }
        }
        // 向左搜索
        if (j > 0 && matrix[n - 1] == str[k] && map.get(n - 1) == null) {
            map.put(n - 1, 0);
            boolean res = scan(matrix, rows, cols, n - 1, str, k + 1, map);
            if (res) {
                return res;
            }
        }
        // 向右搜索
        if (j < cols - 1 && matrix[n + 1] == str[k] && map.get(n + 1) == null) {
            map.put(n + 1, 0);
            boolean res = scan(matrix, rows, cols, n + 1, str, k + 1, map);
            if (res) {
                return res;
            }
        }
        return false;
    }
}
发表于 2020-11-10 15:05:07 回复(0)
递归回溯:
public class Solution {
    private boolean[] isUsed;//标记当前路线下每个位置是否走过
    public boolean hasPath(char[] matrix, int rows, int cols, char[] str) {
        if(rows*cols < str.length) return false;
        isUsed = new boolean[rows*cols];
        for(int i=0; i<rows*cols; i++){//此时先从matrix[i]开始进入,需要找到第一个字符str[0],若找到,则递归查找str[1]
            if(matrix[i] == str[0]){
                isUsed[i] = true;
                boolean find = searchStrByChar(matrix, rows, cols, str, 1, i);
                isUsed[i] = false;
                if(find) return find;
            }
        }
        return false;
    }
    public boolean searchStrByChar(char[] matrix, int rows, int cols, char[] str, int str_pos, int matrix_pos){//递归回溯
        if(str_pos >= str.length) return true;//找完了str即匹配成功,返回true
        int up = matrix_pos - cols;
        int down = matrix_pos + cols;
        int left = matrix_pos - 1;
        int right = matrix_pos + 1;
        boolean find = false;
        if(isInMatrix(rows, cols, up, "up") && matrix[up]==str[str_pos] && !isUsed[up]){
            isUsed[up] = true;
            find = searchStrByChar(matrix, rows, cols, str, str_pos+1, up);
            isUsed[up] = false;
            if(find) return find;
        }
        if(isInMatrix(rows, cols, down, "down") && matrix[down]==str[str_pos] && !isUsed[down]){
            isUsed[down] = true;
            find = searchStrByChar(matrix, rows, cols, str, str_pos+1, down);
            isUsed[down] = false;
            if(find) return find;
        }
        if(isInMatrix(rows, cols, left, "left") && matrix[left]==str[str_pos] && !isUsed[left]){
            isUsed[left] = true;
            find = searchStrByChar(matrix, rows, cols, str, str_pos+1, left);
            isUsed[left] = false;
            if(find) return find;
        }
        if(isInMatrix(rows, cols, right, "right") && matrix[right]==str[str_pos] && !isUsed[right]){
            isUsed[right] = true;
            find = searchStrByChar(matrix, rows, cols, str, str_pos+1, right);
            isUsed[right] = false;
            if(find) return find;
        }
        return false;
    }

    public boolean isInMatrix(int rows, int cols, int target, String pos){
        switch (pos){
            case "up": return target>=0 && target<rows*cols;
            case "down":return target>=0 && target<rows*cols;
            case "left":return (target+1)%cols!=0;
            case "right":return target%cols!=0;
        }
        return false;
    }
}


发表于 2020-10-28 23:45:15 回复(0)
理一下思路:首先这道题很明显和回溯相关。
题目给出是二维数组,但参数确是一维数组加行列,我们可以将其转变为二维数组处理,代码如下
char[][] board = new char[rows][cols];
        int index = 0;
        int x = 0;
        for(int i = 0; i < matrix.length; i++){
            if(index >= cols){
                index = 0;
                x++;
            }
            board[x][index] = matrix[i];
            index++;
        }
对于该矩阵来说,我们从第一个位置开始往后判断,那么代码如下
for(int i = 0; i < rows; i++){
            for(int j = 0; j < cols; j++){
                if(dfs(board, word.toString(), i, j, 0, vis)){
                    return true;
                }
            }
        }
return false;
接下来就是递归加回溯处理,首先确定什么时候递归结束,即当我们找到字符数组中最后一位,成功。那么什么时候失败呢1.越界2.再一次进入进入过的格子3.矩阵没有与字符数组中值相对应的值。
if(i < 0 || i >= board.length || j < 0 || j >= board[0].length || vis[i][j]){
            return false;
        }
        if(str[k] != board[i][j]){
            return false;
        }
        if(k == str.length - 1){
            return true;
        }

若该次字母相对应且没有到最后一位那么,改变当前格子状态,递归等
vis[i][j] = true;
        boolean res = (dfs(board, str, i+1, j, k+1, vis) || dfs(board, str, i-1, j, k+1, vis) ||
                dfs(board, str, i, j+1, k+1, vis) || dfs(board, str, i, j-1, k+1, vis));
vis[i][j] = false;
         
最后总代码如下
public boolean hasPath(char[] matrix, int rows, int cols, char[] str)
    {
      char[][] board = new char[rows][cols];
        int index = 0;
        int x = 0;
        for(int i = 0; i < matrix.length; i++){
            if(index >= cols){
                index = 0;
                x++;
            }
            board[x][index] = matrix[i];
            index++;
        }
      
        boolean[][] vis = new boolean[rows][cols];
        for(int i = 0; i < rows; i++){
            for(int j = 0; j < cols; j++){
                if(dfs(board, str, i, j, 0, vis)){
                    return true;
                }
            }
        }
        return false;
    }
    private boolean dfs(char[][] board, char[] str, int i, int j, int k, boolean[][] vis){
        //越界处理即每个位置只能一次
        if(i < 0 || i >= board.length || j < 0 || j >= board[0].length || vis[i][j]){
            return false;
        }
        if(str[k] != board[i][j]){
            return false;
        }
        if(k == str.length - 1){
            return true;
        }
        vis[i][j] = true;
        boolean res = (dfs(board, str, i+1, j, k+1, vis) || dfs(board, str, i-1, j, k+1, vis) ||
                dfs(board, str, i, j+1, k+1, vis) || dfs(board, str, i, j-1, k+1, vis));
        vis[i][j] = false;
        return res;
    }




发表于 2020-07-21 20:01:00 回复(0)
public class Solution {
    int row_nums;
    int col_nums;
    boolean[] visited;
    int pathLen;
    char[] str_check;

    public  boolean hasPath(char[] matrix, int rows, int cols, char[] str) {
        row_nums = rows;
        col_nums = cols;
        str_check = str;
        if (matrix.length == 0 || row_nums < 1 || col_nums < 1 || str_check.length == 0) {
            return false;
        }
        // 访问记录布尔数组
        visited = new boolean[rows * cols];
        // 字符串路径长度
        pathLen = 0;
        // 遍历矩阵中每一个元素判断能否存在以当前元素为起点的路径
        for (int row = 0; row < rows; row++) {
            for (int col = 0; col < cols; col++) {
                if (hasPthCore(matrix, row, col)) {
                    return true;
                }
            }
        }
        return false;
    }

    private  boolean hasPthCore(char[] matrix, int row, int col) {
        int index = row*col_nums+col;
        boolean hasPath = false;
        // 路径长度等于校验串长度,则表示找到了,终止
        if(pathLen== str_check.length){
            return true;
        }
        // 设置终止条件,在行列范围内,且未访问过
        if (row >= 0 && row < row_nums 
                && col >= 0 && col < col_nums
                && matrix[index] == str_check[pathLen]
                && !visited[index]) {
            // 如果当前串比较字符与矩阵中字符相等,那么路径长度加一,设为已访问
            ++pathLen;
            visited[row * col_nums + col] = true;
            // 向四周扩展
            hasPath = hasPthCore(matrix, row, col - 1)
                    || hasPthCore(matrix, row, col + 1)
                    || hasPthCore(matrix, row - 1, col)
                    || hasPthCore(matrix, row + 1, col);
            // 回溯
            if (!hasPath) {
                --pathLen;
                visited[index] = false;
            }
        }
        return hasPath;
    }
}

发表于 2020-07-10 19:49:30 回复(0)
经典的DFS+回溯。
public class Solution {
    public boolean hasPath(char[] matrix, int rows, int cols, char[] str) {
        boolean[][] isVisited = new boolean[cols][rows];
        for (int i = 0; i < cols; i++) {
            for (int j = 0; j < rows; j++) {
                if (judge(matrix, i, j, rows, cols, isVisited, str, 0)) {
                    return true;
                }
            }
        }
        return false;
    }
    private boolean judge(char[] matrix, int i, int j, int rows, int cols, boolean[][] isVisited, char[] str, int k) {
        if (i < 0 || j < 0 || i >= cols || j >= rows ||
                matrix[j * cols + i] != str[k] || isVisited[i][j]) {
            return false;
        }
        if (k == str.length - 1) return true;
        isVisited[i][j] = true;
        if (judge(matrix, i - 1, j, rows, cols, isVisited, str, k + 1) ||
            judge(matrix, i + 1, j, rows, cols, isVisited, str, k + 1) ||
            judge(matrix, i, j - 1, rows, cols, isVisited, str, k + 1) ||
            judge(matrix, i, j + 1, rows, cols, isVisited, str, k + 1))
            return true;
        isVisited[i][j] = false;
        return false;
    }
}

发表于 2020-06-05 12:27:39 回复(0)
public class Solution {
    
    private int rows;
    private int cols;
    private char[] matrix;
    private char[] str;
    
    public boolean hasPath(char[] matrix, int rows, int cols, char[] str)
    {

        this.rows = rows;
        this.cols = cols;
        this.matrix = matrix;
        this.str = str;
        
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                if (step(i, j, 0)) {
                    return true;
                }
            }
        }
        return false;
    }
    
    private boolean step(int i, int j, int s) {
        if (i < 0 || i >= rows) {
            return false;
        }
        if (j < 0 || j >= cols) {
            return false;
        }
        int pos = i * cols + j;
        if (matrix[pos] != str[s]) {
            return false;
        }
        if (s == str.length - 1) {
            return true;
        }
        char tmp = str[s];
        matrix[pos] = ' ';
        boolean found = step(i-1, j, s+1)
            || step(i+1, j, s+1)
            || step(i, j-1, s+1)
            || step(i, j+1, s+1);
        
        if (found) {
            return true;
        }
        matrix[pos] = tmp;
        return false;
    }
}

编辑于 2020-05-25 21:22:34 回复(0)
public class Solution {
    /**
    经典的回溯
    遍历数组所有元素
    每个元素去找是否是有这样的路径
    */
    public boolean hasPath(char[] matrix, int rows, int cols, char[] str)
    {
        if (null == matrix || matrix.length == 0 || rows < 1 || cols < 1
           || null == str || str.length == 0) {
            return false;
        }
        boolean visited[] = new boolean[matrix.length]; //是否被访问过
        int k = 0; //参与匹配的str的下标
        for(int i=0; i<rows; i++) {
            for(int j=0; j<cols; j++){
                if (hasPath(matrix, rows, cols, i, j, str, k, visited)){
                    return true;
                }
            }
        }
        return false;
    }
    
    private boolean hasPath(char[] matrix, int rows, int cols, 
                            int row, int col, char[] str, int k, boolean visited[]) {
        if (k == str.length) {
            return true;
        }
        boolean result = false;
        if (row>= 0 && row < rows && col < cols && col >= 0
            && matrix[row*cols+col] == str[k] && !visited[row*cols+col]) { //匹配成功
            visited[row*cols+col] = true; //访问过
            k++; //匹配下一个
            result = hasPath(matrix, rows, cols, row-1, col, str, k, visited) //上
                || hasPath(matrix, rows, cols, row+1, col, str, k, visited) //下
                || hasPath(matrix, rows, cols, row, col-1, str, k, visited) //左
                || hasPath(matrix, rows, cols, row, col+1, str, k, visited); //右
            if(!result) {
                k--;
                visited[row*cols+col] = false; //此路不通,设为没访问过
            }    
        }
        return result;
    }


}

发表于 2020-05-17 22:47:58 回复(0)
import java.util.*;
public class Solution {
    boolean[] isVisited = null;

    public boolean hasPath(char[] matrix, int rows, int cols, char[] str) {
        isVisited = new boolean[matrix.length];
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                if (!isVisited[i * cols + j] && help(matrix, rows, cols, str, i, j, 0)) {
                    return true;
                }
            }
        }

        return false;
    }

    public boolean help(char[] matrix, int rows, int cols, char[] str, int row, int col, int len) {
        if (row < 0 || row > rows - 1 || col < 0 || col > cols - 1 || isVisited[row * cols + col] || matrix[row * cols + col] != str[len]) {
            return false;
        }
        if (len == str.length - 1) {
            return true;
        } else {
            isVisited[row * cols + col] = true;
            if (help(matrix, rows, cols, str, row, col + 1, len + 1)) {
                return true;
            } else if (help(matrix, rows, cols, str, row + 1, col, len + 1)) {
                return true;
            } else if (help(matrix, rows, cols, str, row, col - 1, len + 1)) {
                return true;
            } else if (help(matrix, rows, cols, str, row - 1, col, len + 1)) {
                return true;
            } else {
                isVisited[row * cols + col] = false;
                return false;
            }
        }
    }
}
发表于 2020-04-28 12:57:22 回复(0)
递归回溯,需要注意结束的判断条件;参考评论完成代码;
public class Solution {
    public boolean []visited = null;
    public boolean hasPath(char[] matrix, int rows, int cols, char[] str)
    {
        visited = new boolean[matrix.length];
        for(int i=0;i<rows;i++){
            for(int j=0;j<cols;j++){//由于是任意的格子开始;所以需要遍历矩阵;
                if(subHashPath(matrix,rows,cols,str,i,j,0))//0表示从字符str0的位置开始;
                    return true;
            }
        }
        return false;
    }
    public boolean subHashPath(char [] matrix,int rows,int cols,char [] str,int i,int j,int cur){
        if(matrix[i*cols+j]!=str[cur]||visited[i*cols+j]==true) return false;
        if(cur==str.length-1) return true;//有值,递归结束判断条件;已经到达最后一个字符
        visited[i*cols+j]=true;//表明值相同,该点标记访问过;
        //以下开始递归从该点的上下左右出发;
        if(i>0 && subHashPath(matrix,rows,cols,str,i-1,j,cur+1)) return true;
        if(i<rows-1 && subHashPath(matrix,rows,cols,str,i+1,j,cur+1)) return true;
        if(j>0 && subHashPath(matrix,rows,cols,str,i,j-1,cur+1)) return true;
        if(j<cols-1 && subHashPath(matrix,rows,cols,str,i,j+1,cur+1)) return true;
        //以上都不成立;则退到上一节点,标记取消;
        visited[i*cols+j]=false;
        //该点以下不可通,返回false
        return false;
    }
}


发表于 2020-04-27 16:05:13 回复(0)
public class Solution {
    public boolean hasPath(char[] matrix, int rows, int cols, char[] str)
    {
        char[][] map = new char[rows][cols];
        int[][] visited = new int[rows][cols];
        
        for (int i=0;i<rows;i++) {
            for (int j=0;j<cols;j++) {
                map[i][j] = matrix[i * cols + j];
            }
        }
        for (int i=0;i<rows;i++) {
            for (int j=0;j<cols;j++) {
                if ( hasStep(map, visited, i, j, str, 0) ) {
                    return true;
                }
            }
        }
        return false;
    }
    boolean hasStep(char[][] map, int[][] visited, int x, int y, char[] str, int index) {
        if (x < 0 || x >= map.length || y < 0 || y >= map[0].length
           || str[index] != map[x][y]
           || visited[x][y] == 1) {
            return false;
        }
        if (index == str.length-1) {
            return true;
        }
        visited[x][y] = 1;
        
        boolean flag = hasStep(map, visited, x-1, y, str, index+1)
            || hasStep(map, visited, x+1, y, str, index+1)
            || hasStep(map, visited, x, y-1, str, index+1)
            || hasStep(map, visited, x, y+1, str, index+1);
        visited[x][y] = 0;
        return flag;
    }

}

public class Solution {
public boolean hasPath(char[] matrix, int rows, int cols, char[] str)
{
char[][] map = new char[rows][cols];
int[][] visited = new int[rows][cols];

for (int i=0;i<rows;i++) {
for (int j=0;j<cols;j++) {
map[i][j] = matrix[i * cols + j];
}
}
for (int i=0;i<rows;i++) {
for (int j=0;j<cols;j++) {
if ( hasStep(map, visited, i, j, str, 0) ) {
return true;
}
}
}
return false;
}
boolean hasStep(char[][] map, int[][] visited, int x, int y, char[] str, int index) {
if (x < 0 || x > map.length - 1 || y < 0 || y > map[0].length - 1
|| str[index] != map[x][y]
|| visited[x][y] == 1) {
return false;
}
visited[x][y] = 1;
if (index == str.length - 1) {
return true;
}
if ( hasStep(map, visited, x + 1, y, str, index + 1) ) {
return true;
}
if ( hasStep(map, visited, x, y + 1, str, index + 1) ) {
return true;
}
if ( hasStep(map, visited, x - 1, y, str, index + 1) ) {
return true;
}
if ( hasStep(map, visited, x, y - 1, str, index + 1) ) {
return true;
}
visited[x][y] = 0;
return false;
}

}
编辑于 2020-07-24 21:34:12 回复(0)
/*将矩阵翻译成图结构,这样寻找路径的时候只需要查看邻接点,而不需要查看是否越界。
*/
public class Solution {
     public boolean hasPath(char[] matrix, int rows, int cols, char[] str){
         GraphNode[] graph=translateToGraph(matrix,rows,cols);
         for(GraphNode n:graph) {
             if(searchPath(n,str,0))
                 return true;
         }
         return false;
         
     }
    public static boolean searchPath(GraphNode node, char[] str,int index) {
        if(index>=str.length)
            return true;
        if(node.isVisited || node.val!=str[index])
            return false;
        if(index==str.length-1)
            return true;
        node.isVisited=true;
        for(int i=0;i<node.countNext;i++) {
            if(searchPath(node.next[i],str,index+1)) {
                node.isVisited=false;
                return true;
            }
        }
        node.isVisited=false;
        return false;
            
    }
    public static GraphNode[] translateToGraph(char[] matrix, int rows, int cols) {
         GraphNode[] nodes=new GraphNode[matrix.length];
         for(int i=0;i<matrix.length;i++)
             nodes[i]=new GraphNode(matrix[i]);
         for(int r=0;r<rows;r++) {
             int initial=r*cols;
             int end=initial+cols-1;
             for(int i=initial;i<end;i++) {
                 nodes[i].addNext(nodes[i+1]);
                 nodes[i+1].addNext(nodes[i]);
             }
         }
         for(int c=0;c<cols;c++) {
             int initial=c;
             int end=matrix.length-cols;
             for(int i=initial;i<end;i+=cols) {
                 nodes[i].addNext(nodes[i+cols]);
                 nodes[i+cols].addNext(nodes[i]);
             }
         }
         return nodes;
     }
     
}

class GraphNode{
    char val=' ';
    int countNext=0;
    boolean isVisited=false;
    GraphNode[] next=new GraphNode[] {null,null,null,null};
    GraphNode(){}
    GraphNode(char c){
        val=c;
    }
    void addNext(GraphNode n) {
        next[countNext++]=n;
    }
    
    
}
发表于 2020-04-15 08:27:49 回复(0)
其实就是深度优先搜索算法,只不过不需要借助栈来实现,如果能就一条路走到返回true,如果不能就退一步再试试一条路走到黑,使用递归从而代替了栈
public class Solution {
    public boolean hasPath(char[] matrix, int rows, int cols, char[] str) {
        if(matrix.length==0||matrix.length<str.length){
            return false;
        }
        for(int i = 0;i<matrix.length;i++){
            if(matrix[i]==str[0]){
                int[] verify = new int[matrix.length];
                verify[i] = 1;
                int h = i/cols;
                int w = i%cols;
                if(str.length==1){
                    return true;
                }
                if(helper(matrix,rows,cols,str,h,w,verify)){
                    return true;
                }
            }
        }
        return false;
    }

    public boolean move(char[] matrix, int rows,
                        int cols, char[] str,int h,int w,int[] verify){
        if(h>=0&&w>=0&&h<rows&&w<cols&&h*cols+w<matrix.length){
            if(verify[h*cols+w]!=1&&matrix[h*cols+w]==str[0]){
                verify[h*cols+w] = 1;
                if(str.length==1){
                    return true;
                }else {
                    return helper(matrix,rows,cols,str,h,w,verify);
                }
            }else{
                return false;
            }
        }else{
            return false;
        }
    }

    public boolean helper(char[] matrix, int rows, int cols, char[] str,int h,int w,int[] verify){
        if(move(matrix,rows,cols,removeFirst(str),h-1,w,verify)||
                move(matrix,rows,cols,removeFirst(str),h+1,w,verify)||
                move(matrix,rows,cols,removeFirst(str),h,w-1,verify)||
                move(matrix,rows,cols,removeFirst(str),h,w+1,verify)){
            return true;
        }else{
            return false;
        }
    }

    public char[] removeFirst(char[] chars1){
        char[] chars2 = new char[chars1.length-1];
        if(chars2.length<=0){
            return new char[]{};
        }
        for(int i= 0;i<chars2.length;i++){
            chars2[i] = chars1[i+1];
        }
        return chars2;
    }



}


发表于 2020-04-13 13:53:12 回复(0)

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


讲讲为什么用DFS,而不能用BFS (个人看法,有误请批!
这道题首先看出是DFS(深搜)问题,(为何是DFS,DFS就是用来不停探寻下一步,直至能否到达目的点,而另一种是BFS(广搜),BFS是用来找到源点到终点的最短路径。如果用BFS求解这道题,嗯?确定能用吗?BFS是以源点向四周扩散,以最短的扩散次数找到源点,听起来好像可以,我们可以一次次扩散找到路径中的每一个点,但是一般的BFS扩散一次,会把走过的结点标志为不可以走,那么假如第一个结点A四周扩散一次,四周走过,恰巧右方是第二个结点B,下方是最后一个结点E,那么以B怎么扩散都不能访问到E,因为E被走过,B怎么走都走不到E,所以个人觉得BFS不能用来解决这道题,只能用DFS一条路走到黑的方式来解决)


这道题就是以矩阵中的每一个点作为为起点去执行一次DFS。而DFS的执行过程就是:

  1. 每次执行DFS先判断走过的路径是不是等于要求的路径,是就返回结果true,不是就继续找。
  2. 先判断当前点是否可走,不是,则返回上一层;是就顺时针探寻下一个方位的结点(上、右、下、左),以下一个方位结点进行DFS,如果方位都探完了还找不到路径,那么当前节点不可能是路径结点之一,只能返回上一层。

Java代码实现

public class Solution {
    private boolean visited[] = null;//标志每个位置是否走过,true走过,false没走过

    public boolean hasPath(char[] matrix, int rows, int cols, char[] str) {
        if (matrix == null || str == null || str.length > matrix.length || rows * cols != matrix.length)
            //进行非法性判断
            return false;
        //初始化visited数组
        visited = new boolean[rows * cols];
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                //以每个结点作为起始节点去dfs
                if (dfs(matrix, i, j, rows, cols, str, 0))
                    return true;
            }
        }
        //没有找到
        return false;
    }

    /**
     * @param matrix 地图
     * @param x      起点x
     * @param y      起点y
     * @param rows   行数
     * @param cols   列数
     * @param str    所求路径
     * @param len    当前已经找到路径的长度
     * @return
     */
    private boolean dfs(char[] matrix, int x, int y, int rows, int cols, char[] str, int len) {
        if (len >= str.length) {
            //找到要求的路径
            return true;
        } else {
            //路径长度小于要求的长度,还得继续寻找
            if (x >= 0 && x <= rows - 1 && y >= 0 && y <= cols - 1 && visited[x * cols + y] == false && matrix[x * cols + y] == str[len]) {
                //当前结点是路径节点之一
                visited[x * cols + y] = true;//把当前结点的标志位设为true,证明走过了
                //寻找下一方位
                int dict = 0;
                int x1 = 0, y1 = 0;
                while (dict <= 3) {
                    switch (dict) {
                        case 0: x1 = x - 1; y1 = y; break;
                        case 1: x1 = x ; y1 = y + 1; break;
                        case 2: x1 = x + 1; y1 = y; break;
                        case 3: x1 = x ; y1 = y - 1; break;
                    }
                    if(dfs(matrix, x1, y1, rows, cols, str, len + 1))//判断下一个方位能否找到路径
                        return true; //能,直接返回
                    dict ++;//不能,找下一方位
                }
                //不能从当前结点找不到路径,那就回溯,把当前结点标志位设为false
                visited[x * cols + y] = false;
                return false;//返回失败
            } else{
                //当前结点不是要找的路径,直接回溯
                return false;
            }
        }
    }
}
发表于 2020-04-12 00:59:35 回复(0)

问题信息

难度:
98条回答 109641浏览

热门推荐

通过挑战的用户

矩阵中的路径