跳至主要內容

矩阵中的路径

soulballad算法剑指Offer剑指Offer约 786 字大约 3 分钟

题目:

请设计一个函数,用来判断在一个矩阵中是否存在一条包含否字符串所有字符的路径。路径可以从矩阵中任意一格开始,每一步可以在矩阵中向左、右、上、下移动一格。如果一条路径经过了矩阵的某一格,那么该路径不能再次进入该格子。例如,在下面的 3x4 的矩阵中包含一条字符串 “bfce” 的路径(路径中的字母用下划线标出)。但矩阵中不包含字符串 “abfd” 的路径,因为字符串的第一个字符 b 占据了矩阵中的第一行第二个格子之后,路径不能再进入这个格子。

​ a b t g

​ c f c s

​ j d e g

分析:本题可以使用回溯法。

回溯法:

回溯算法实际上是一个类似枚举的搜索尝试过程,在搜索过程中寻找问题的解,当发现当前问题状态无解时,就 “回溯” 返回,尝试别的路径。

判断回溯很简单,拿到一个问题,你感觉如果不穷举一下就没法知道答案,那就可以开始回溯了。

这个一个走路径的问题,需要判断这个矩阵中的每一个结点是否可以走一条路径,在走的过程中,设置一个和矩阵大小相同的整型数组表示是否已经访问,如果某个结点访问了,那么该结点的是否访问则为1。每次遍历一个结点的时候,递归的方式分别向左、向右、向上、向下。

代码:

/**
 * 判断路径是否存在
 *
 * @param matrix 矩阵,用二维数组表示
 * @param rows   总行数
 * @param cols   总列数
 * @param path   要查找的路径
 */
public static boolean hasPath(char[][] matrix, int rows, int cols, char[] path) {

    int[] flag = new int[rows * cols];

    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
            if (hasChar(matrix, rows, cols, i, j, path, 0, flag)) {
                return true;
            }
        }
    }

    return false;
}

/**
 * 判断字符是否存在
 *
 * @param matrix 矩阵,用二维数组表示
 * @param rows   总行数
 * @param cols   总列数
 * @param row    当前行
 * @param col    当前列
 * @param path   查找路径
 * @param index  path中下标
 * @param flag   已访问元素标记
 */
private static boolean hasChar(char[][] matrix, int rows, int cols, int row, int col, char[] path, int index, int[] flag) {
    // 判断字符是否被使用过的位置标记
    int unique = row * cols + col;

    // 不是要访问的字符,或者已经被访问过,直接返回false
    if (row < 0 || row >= rows || col < 0 || col >= cols || matrix[row][col] != path[index] || flag[unique] == 1) {
        return false;
    }

    // 已经是path里面最后一个字符
    if (index == path.length - 1) {
        return true;
    }

    // 标记为已访问
    flag[unique] = 1;
    // 分别向上、向下、向左、向右遍历
    if (hasChar(matrix, rows, cols, row - 1, col, path, index + 1, flag)
            || hasChar(matrix, rows, cols, row + 1, col, path, index + 1, flag)
            || hasChar(matrix, rows, cols, row, col - 1, path, index + 1, flag)
            || hasChar(matrix, rows, cols, row, col + 1, path, index + 1, flag)) {
        return true;
    }

    flag[unique] = 0;
    return false;
}
上次编辑于:
贡献者: soulballad