《剑指offer》——矩阵中的路径

来源:互联网 发布:iphone清理缓存软件 编辑:程序博客网 时间:2024/06/06 17:55

T:

题目描述
请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向上,向下移动一个格子。如果一条路径经过了矩阵中的某一个格子,则该路径不能再进入该格子。 例如 a b c e s f c s a d e e 矩阵中包含一条字符串”bccced”的路径,但是矩阵中不包含”abcb”路径,因为字符串的第一个字符b占据了矩阵中的第一行第二个格子之后,路径不能再次进入该格子。

这个题目,还是有点儿bug的,举例都弄错了,”bccced”应改为”bcced”。

这个题目,我第一个想到的方法,就是递归。忽然发现,好多问题,都可以用递归解决。。。

这个代码,也是修改了好几次,总是有很多小bug,总的来说,不算好代码,但也毕竟是自己吭哧吭哧了一个小时搞出来的东西,还是应该贴一下。

code:

    package niuke.sward2offer.pathInMatrix;    import java.util.ArrayList;    /**     * T: 矩阵中的路径     *      * 题目描述     * 请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。     * 路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向上,向下移动一个格子。     * 如果一条路径经过了矩阵中的某一个格子,则该路径不能再进入该格子。      * 例如 a b c e s f c s a d e e 矩阵中包含一条字符串"bccced"的路径,     * 但是矩阵中不包含"abcb"路径,因为字符串的第一个字符b占据了矩阵中的第一行第二个格子之后,路径不能再次进入该格子。     *      * date: 2015.11.5      * @author SSS     *     */    public class Solution {        public boolean  hasPath(char []matrix, int rows, int cols, char[] str) {            boolean flag = false;            // 将一维数组转变为二维数组,方便处理            char [][]newMatrx = new char[rows][cols];            for (int i = 0; i < matrix.length; i++) {                newMatrx[i/cols][i%cols] = matrix[i];            }            // 标记位,若已经访问过,那就置为1,否则置为0            int [][]flagMatrix = new int[rows][cols];            for (int i = 0; i < flagMatrix.length; i++) {                for (int j = 0; j < flagMatrix[0].length; j++) {                    flagMatrix[i][j] = 0;                 }            }            // 将char型的数组也转变为String,方便计算            String newStr = String.valueOf(str);            /**             * 对于二维数组中的元素,逐个匹配,即使第一次匹配成功了,也要继续往下匹配,             * 以防这一次的不成功,而成功的路径在下一次的匹配上             */            for (int i = 0; i < newMatrx.length; i++) {                for (int j = 0; j < newMatrx[0].length; j++) {                    if (newMatrx[i][j] == str[0]) {                        flagMatrix[i][j] = 1;                        if (newStr.length() == 1) {                            flag = true;                        } else {                            flag = this.getResult(newMatrx, flagMatrix, i, j, newStr.substring(1));                        }                        if (flag) {                            break;                        }                        // 如果不匹配,要重新置为0                        flagMatrix[i][j] = 0;                    }                }                if (flag) {                    break;                }            }            return flag;        }        /**         * 递归函数:在newMatrix这个二维数组内,当前的位置处在【rows】和【cols】上,         * 那就从上下左右一次寻找,寻找该点周围的其他点,是否有和newStr的第一个字母相同的,         * 如果有相同的,那就进行下一次的递归;如果不相同,那就返回false.         *          * 终止条件:         * 当前函数中的newStr字符串的长度为1,然后再在该点周围的四个方向上找         * 是否有和该字母相同的,如果相同,那就返回true,否则就返回false         *          * 方法略笨了些,应该还可以进一步简化         *          * @param newMatrix         * @param flagMatrix         * @param aIndex         * @param bIndex         * @param newStr         * @return         */        public boolean getResult(char [][]newMatrix, int [][]flagMatrix, int aIndex, int bIndex, String newStr) {            char temp= newStr.charAt(0);            if (newStr.length() == 1) {                //左                if (bIndex > 0 && flagMatrix[aIndex][bIndex - 1] == 0 && newMatrix[aIndex][bIndex - 1] == temp) {                    return true;                }                // 上                if (aIndex > 0 && flagMatrix[aIndex - 1][bIndex] == 0 && newMatrix[aIndex - 1][bIndex] == temp) {                    return true;                }                // 右                if (bIndex < (flagMatrix[0].length - 1) && flagMatrix[aIndex][bIndex + 1] == 0 && newMatrix[aIndex][bIndex + 1] == temp) {                    return true;                }                // 下                if (aIndex < (flagMatrix.length - 1) && flagMatrix[aIndex + 1][bIndex] == 0 && newMatrix[aIndex + 1][bIndex] == temp) {                    return true;                }                return false;            }            boolean flag = false;            if (bIndex > 0 && flagMatrix[aIndex][bIndex - 1] == 0 && newMatrix[aIndex][bIndex - 1] == temp) {                flagMatrix[aIndex][bIndex - 1] = 1;                flag = this.getResult(newMatrix, flagMatrix, aIndex, bIndex - 1, newStr.substring(1));            }            if (aIndex > 0 && flagMatrix[aIndex - 1][bIndex] == 0 && newMatrix[aIndex - 1][bIndex] == temp && flag == false) {                flagMatrix[aIndex - 1][bIndex] = 1;                flag = this.getResult(newMatrix, flagMatrix, aIndex - 1, bIndex, newStr.substring(1));            }            if (bIndex < (flagMatrix[0].length - 1) && flagMatrix[aIndex][bIndex + 1] == 0 && newMatrix[aIndex][bIndex + 1] == temp && flag == false) {                flagMatrix[aIndex][bIndex + 1] = 1;                flag = this.getResult(newMatrix, flagMatrix, aIndex, bIndex + 1, newStr.substring(1));            }            if (aIndex < (flagMatrix.length - 1) && flagMatrix[aIndex + 1][bIndex] == 0 && newMatrix[aIndex + 1][bIndex] == temp && flag == false) {                flagMatrix[aIndex + 1][bIndex] = 1;                flag = this.getResult(newMatrix, flagMatrix, aIndex + 1, bIndex, newStr.substring(1));            }            return flag;        }        public static void main(String []args) {            char [] matrix = {'A'};            int rows = 1;            int cols = 1;            char []str = {'A'};        //  String ss = String.valueOf(str);            Solution solution = new Solution();            System.out.println(solution.hasPath(matrix, rows, cols, str));        }    }

看到别人写的,也有很简洁的代码,但是,在我看来,简洁未必就是最好,反而一些易读的代码才更受欢迎,还一个就是解题思路,也比代码的简洁更重要。

别人的code:

    /**    用一个状态数组保存之前访问过的字符,然后再分别按上,下,左,右递归    */    public class Solution {        public boolean hasPath(char[] matrix, int rows, int cols, char[] str) {            int flag[] = new int[matrix.length];            for (int i = 0; i < rows; i++) {                for (int j = 0; j < cols; j++) {                    if (helper(matrix, rows, cols, i, j, str, 0, flag))                        return true;                }            }            return false;        }        private boolean helper(char[] matrix, int rows, int cols, int i, int j, char[] str, int k, int[] flag) {            int index = i * cols + j;            if (i < 0 || i >= rows || j < 0 || j >= cols || matrix[index] != str[k] || flag[index] == 1)                return false;            if(k == str.length - 1) return true;            flag[index] = 1;            if (helper(matrix, rows, cols, i - 1, j, str, k + 1, flag)                    || helper(matrix, rows, cols, i + 1, j, str, k + 1, flag)                    || helper(matrix, rows, cols, i, j - 1, str, k + 1, flag)                    || helper(matrix, rows, cols, i, j + 1, str, k + 1, flag)) {                return true;            }            flag[index] = 0;            return false;        }    }

对代码略做解释:

子函数helper(…)的含义是在当前的二维数组的(i, j)这个位置,与str数组的第k项值是否相等,当然前提是该位置之前并没有走过。
本代码中,仍然沿用一维数组,这是值得学习的地方,另外一个,就是终止条件的运用,在该代码中,把下标越界也当做一个终止条件,这是我之前没有想到的。

下面再贴一个我重新按照此思想码的代码。哎,看着别人写的代码,感觉很容易就能实现,但当自己一点点的去码的时候,会发现各种bug。。。

code:

    package niuke.sward2offer.pathInMatrix;    /**     * 重写的代码     *      * T: 矩阵中的路径     *      * 题目描述     * 请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。     * 路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向上,向下移动一个格子。     * 如果一条路径经过了矩阵中的某一个格子,则该路径不能再进入该格子。      * 例如 a b c e s f c s a d e e 矩阵中包含一条字符串"bccced"的路径,     * 但是矩阵中不包含"abcb"路径,因为字符串的第一个字符b占据了矩阵中的第一行第二个格子之后,路径不能再次进入该格子。     *      * date: 2015.11.5      * @author SSS     *     */    public class Solution1 {        public boolean hasPath(char []matrix, int rows, int cols, char []str) {            // 标记位            int []flagMatrix = new int[matrix.length];            for (int i = 0; i < flagMatrix.length; i++) {                flagMatrix[i] = 0;            }            for (int i = 0; i < rows; i++) {                for (int j = 0; j < cols; j++) {                    int index = cols * i + j;                    if (str[0] == matrix[index]) {  // 只有在第一个相等的时候才进行比较,否则直接略过,效率更高                        if (str.length == 1) {  // 要判断该str的长度是否只为1,如果是1,那就不用子函数                            return true;                        }                        if (this.isHasPath(matrix, flagMatrix, rows, cols, i, j, str, 0)) {                            return true;                        }                    }                }            }            return false;        }        public boolean isHasPath(char []matrix, int []flagMatrix, int rows, int cols, int a, int b, char []str, int k) {            int index = cols * a + b;            if (k == str.length) {                return true;            }            if (a < 0 || a == rows || b < 0 || b == cols || flagMatrix[index] == 1 || matrix[index] != str[k]) {                return false;            }            flagMatrix[index] = 1;            if (this.isHasPath(matrix, flagMatrix, rows, cols, a, b - 1, str, k + 1)                     || this.isHasPath(matrix, flagMatrix, rows, cols, a - 1, b, str, k + 1)                    || this.isHasPath(matrix, flagMatrix, rows, cols, a, b + 1, str, k + 1)                    || this.isHasPath(matrix, flagMatrix, rows, cols, a + 1, b, str, k + 1)                    ) {                return true;            }            flagMatrix[index] = 0;            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 = {'A','B','C','C','E','D'};        //  String ss = String.valueOf(str);            Solution1 solution1 = new Solution1();            System.out.println(solution1.hasPath(matrix, rows, cols, str));        }    }
0 0