[剑指Offer]-矩阵中的路径

题目描述

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

我就觉得这递归思想就是一个反人类的思想!

回溯法找路径,可以看作下面的一个树结构,在每个满足条件的节点,寻找到相邻的节点,然后在相邻节点里面找个满足第i步的元素,如果找不到就回退一步。

[剑指Offer]-矩阵中的路径

解题思路

  • 遍历矩阵找到一个入口。
  • 定义一个数组用于储存当前节点是否遍历过的信息。
  • 寻找相邻节点是否有满足条件的节点。
    • 下面代码中,当矩阵坐标为(row,col)的格子和路径字符串中下标为pathLength的字符一样时,从4个相邻的格子(row,col-1)、(row-1,col)、(row,col+1)以及(row+1,col)中去定位路径字符串中下标为pathLength+1的字符。
    • 如果4个相邻的格子都没有匹配字符串中下标为pathLength+1的字符,表明当前路径字符串中下标为pathLength的字符在矩阵中的定位不正确,我们需要回到前一个字符串(pathLength-1),然后重新定位。

一直重复这个过程,直到路径字符串上所有字符都在矩阵中找到格式的位置(此时pathLength>startch.length-1 )。

算法图解

[剑指Offer]-矩阵中的路径

  • 注意代码中对于结束递归的条件的设定!
  • 是否访问数组的赋值!
参考代码:
package offer;

import java.util.Arrays;

public class Offer12 {
    public static void main(String[] args) {
        char nums[][] = {{'a', 'b', 't', 'g'}, {'c', 'f', 'c', 's'}, {'j', 'd', 'e', 'h'}};
        int rows = nums.length;
        int cols = nums[0].length;
        char startch[] = {'b', 'f', 'c', 'h'};
        boolean tag = hashPath(nums, rows, cols, startch);
        if (tag) {
            System.out.println("存在路径");
        } else {
            System.out.println("不存在路径");
        }

    }

    static boolean hashPath(char nums[][], int rows, int cols, char startch[]) {

        if (nums == null || rows <= 1 || cols <= 1 || startch == null) {
            return false;
        }
        boolean visited[] = new boolean[rows * cols];
        Arrays.fill(visited, false);
        int pathLength = 0;
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                if (hashPathCore(nums, i, j, rows, cols, startch, pathLength, visited)) {
                    return true;
                }
            }
        }
        return false;
    }

    private static boolean hashPathCore(char[][] nums, int row, int col, int rows, int cols, char[] startch, int pathLength, boolean[] visited) {
        if (pathLength>startch.length-1 ) {
            return true;
        }
        boolean hasPath = false;
        if (row < rows && col < cols && col >= 0 && row >= 0 && nums[row][col] == startch[pathLength] && !visited[row * cols + col]) {
            ++pathLength;
            visited[row * cols + col] = true;
            hasPath = hashPathCore(nums, row - 1, col, rows, cols, startch, pathLength, visited)
                    || hashPathCore(nums, row + 1, col, rows, cols, startch, pathLength, visited)
                    || hashPathCore(nums, row, col - 1, rows, cols, startch, pathLength, visited)
                    || hashPathCore(nums, row, col + 1, rows, cols, startch, pathLength, visited);
            if (!hasPath) {
                --pathLength;
                visited[row * cols + col] = false;
            }
        }
        return hasPath;
    }
}



附录

该题源码在我的 ????Github 上面!