[剑指offer] 矩阵中的路径

Description:

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

  a      b      t         g

  c      f       c        s

   j      d      e        h 

 矩阵中包含一条字符串"bfce"的路径,但是矩阵中不包含"abfb"路径,因为字符串的第一个字符b占据了矩阵中的第一行第二个格子之后,路径不能再次进入该格子。

 

 

Solution:

public class Solution {
    public boolean hasPath(char[] matrix, int rows, int cols, char[] str)
    {
        boolean [][] visited = new boolean[rows][cols]; // 标记每个格子是否已经进入过
        int[] pathLength = new int[1];                  // 记录当前得到的路径长,初始值为0
        
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                if (hasPathCore(matrix, i, j, rows, cols, str, pathLength, visited)) {
                    return true;
                }
            }
        }
        return false;
    }

    public boolean hasPathCore(char[] matrix, int row, int col, int rows, int cols, char[] str, int[] pathLength, boolean[][] visited) {
        if (pathLength[0] == str.length)
            return true;    // 找到完整路径
        
        boolean hasPath = false;
        if (row < rows && row >= 0 && col < cols && col >= 0 &&
            str[pathLength[0]] == matrix[row*cols+col] && !visited[row][col]) {
            // 当矩阵中坐标为(row, col)的格子和路径字符串中下标为pathLength的字符一样时,
            ++pathLength[0];
            visited[row][col] = true;
            // 从四个相邻的格子去定位字符串中下标为pathLength+1的字符
            hasPath = hasPathCore(matrix, row, col-1, rows, cols, str, pathLength, visited) ||
                      hasPathCore(matrix, row-1, col, rows, cols, str, pathLength, visited) ||
                      hasPathCore(matrix, row, col+1, rows, cols, str, pathLength, visited) ||
                      hasPathCore(matrix, row+1, col, rows, cols, str, pathLength, visited);
            // 找不到路径 -> 回溯
            if (!hasPath) {
                --pathLength[0];
                visited[row][col] = false;
            }
        }
        return hasPath;
    }
}

 

Key Points :

  • 由于矩阵中的每个节点都有可能作为路径的起点,所以需要遍历整个矩阵对每个节点作为起点的所有路径做检查。
  • 用变量pathLength作为标记计数器,当pathLength的值等于目标路径的长度时,表示能在矩阵中找到目标路径,这是递归的出口。由于Java中基本数据类型只支持值传递,而寻找路径需要递归调用,所以需要传递一个长度为1的数组作为参数。
  • 矩阵是一个有界的区域,在检查时需要用row和col的值限制来防止越界
  • 在每个节点移动到下一个节点都考虑向上、向下、向左、向右移动四种情况,只要任一方向能找到当前的目标字符,即认为在当前进度下,目标路径是可能存在的,用hasPath标记。
  • 关键的回溯条件是:当前寻找的路径碰到一个节点,无论往什么方向移动都无法找到下一个目标字符,即hasPath == false,回溯需要把pathLength的长度-1,当前访问的位置重新设置为未访问状态(visited[row][col] = false)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值