10.矩阵中的路径

本题知识点:数组

题目描述

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

\begin{bmatrix} a & b & c &e \\ s & f & c & s \\ a & d & e& e\\ \end{bmatrix}

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

a b c e
s f c s
a d e e

解题思路

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

代码实现

java 代码

    /**
     * 回溯法查找路径是否存在
     * @param matrix 矩阵数组
     * @param rows 矩阵行数
     * @param cols 矩阵列数
     * @param str 查找字符串路径数组
     * @return
     */
    public boolean hasPath(char[] matrix, int rows, int cols, char[] str) {
        //创建和矩阵相同大小的标志位数组
        boolean[] flag = new boolean[matrix.length];
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                //查找字符串路径的起始位,开始向四周搜索路径
                if(judge(matrix, rows, cols, i, j, str, 0, flag)){
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * 回溯法查找路径是否存在
     * @param matrix 矩阵数组
     * @param rows 矩阵行数
     * @param cols 矩阵列数
     * @param i 当前行数坐标
     * @param j 当前列数坐标
     * @param str 查找字符串路径数组
     * @param n 当前字符串数组中查到当前位数
     * @param flag 标记路径中是否已经进入的标志
     * @return
     */
    public boolean judge(char[] matrix, int rows, int cols, int i, int j, char[] str, int n, boolean[] flag) {
        //判断当前坐标是否越界,如果越界,则不在矩阵内,返回false
        if (i < 0 || j < 0 || i >= rows || j >= cols) {
            return false;
        }
        //根据矩阵坐标转换为数组下标
        int index = i * cols + j;
        //判断盖数组下标的格子是否已经进入,如果进入,则不能再次进入,返回false
        if (flag[index]) {
            return false;
        }
        //判断查找的字符串路径当前字符与数组中当前下标的字符是否相同,如果不相同,则当前格子不存在路径,返回false
        if (str[n] != matrix[index]) {
            return false;
        }
        //判断已经查找到字符串最后一位,则路径存在,返回true
        if (n + 1 == str.length) {
            return true;
        }
        //当前位置表示当前格子符合字符串查找路径中当当前位置n,将该格子标记为true,避免下一个格子搜索时进入
        flag[index] = true;
        //开始搜索字符串查找路径当前位置的下一个字符路径,分布查找当前格子上,下,左,右的格子是否存在下一个字符的路径
        if (judge(matrix, rows, cols, i - 1, j, str, n + 1, flag)
                || judge(matrix, rows, cols, i + 1, j, str, n + 1, flag)
                || judge(matrix, rows, cols, i, j - 1, str, n + 1, flag)
                || judge(matrix, rows, cols, i, j + 1, str, n + 1, flag)
        ) {
            //下一个字符路径存在,则当前格子路径正确,返回true
            return true;
        } else {
            //下一个字符路径不存在,当前格子路径不正确,则将当前格子标志位置为false(回溯),可以允许其他格子检查时进入
            flag[index] = false;
            return false;
        }
    }

    public static void main(String[] args){
         char[] matrix = {'a','b','c','e','s','f','c','s','a','d','e','e'};
        int rows = 3;
        int cols = 4;
        char[] str = "bccfd".toCharArray();
        System.out.println(hasPath(matrix,rows,cols,str));
    }

Kotlin 代码

     /**
     * 回溯法查找路径是否存在
     * @param matrix 矩阵数组
     * @param rows 矩阵行数
     * @param cols 矩阵列数
     * @param i 当前行数坐标
     * @param j 当前列数坐标
     * @param str 查找字符串路径数组
     * @param n 当前字符串数组中查到当前位数
     * @param flag 标记路径中是否已经进入的标志
     * @return
     */
    private fun judge(
        matrix: CharArray,
        rows: Int,
        cols: Int,
        i: Int,
        j: Int,
        str: CharArray,
        n: Int,
        flag: BooleanArray
    ): Boolean {
        //判断当前坐标是否越界,如果越界,则不在矩阵内,返回false
        if (i < 0 || j < 0 || i >= rows || j >= cols) {
            return false
        }
        //根据矩阵坐标转换为数组下标
        val index = i * cols + j
        //判断盖数组下标的格子是否已经进入,如果进入,则不能再次进入,返回false
        if (flag[index]) {
            return false
        }
        //判断查找的字符串路径当前字符与数组中当前下标的字符是否相同,如果不相同,则当前格子不存在路径,返回false
        if (str[n] != matrix[index]) {
            return false
        }
        //判断已经查找到字符串最后一位,则路径存在,返回true
        if (n + 1 == str.size) {
            return true
        }
        //当前位置表示当前格子符合字符串查找路径中当当前位置n,将该格子标记为true,避免下一个格子搜索时进入
        flag[index] = true
        //开始搜索字符串查找路径当前位置的下一个字符路径,分布查找当前格子上,下,左,右的格子是否存在下一个字符的路径
        return if (judge(matrix, rows, cols, i - 1, j, str, n + 1, flag)
            || judge(matrix, rows, cols, i + 1, j, str, n + 1, flag)
            || judge(matrix, rows, cols, i, j - 1, str, n + 1, flag)
            || judge(matrix, rows, cols, i, j + 1, str, n + 1, flag)
        ) {
            //下一个字符路径存在,则当前格子路径正确,返回true
            true
        } else {
            //下一个字符路径不存在,当前格子路径不正确,则将当前格子标志位置为false(回溯),可以允许其他格子检查时进入
            flag[index] = false
            false
        }
    }

    /**
     * 入口函数
     */
    fun main(args: Array<String>) {
        val matrix =
            charArrayOf('a', 'b', 'c', 'e', 's', 'f', 'c', 's', 'a', 'd', 'e', 'e')
        val rows = 3
        val cols = 4
        val str = "bccfd".toCharArray()
        println(hasPath(matrix, rows, cols, str))
    }

引用声明

该题目引用自
牛客网