剑指offer_12_矩阵中的路径【javascript】

105 阅读2分钟

题目

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

a b t g
c f c s
j d e h

示例1

输入:board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "ABCCED"
输出:true

示例 2:

输入:board = [["a","b"],["c","d"]], word = "abcd"
输出:false

题解

回溯法

/**
 * @param {character[][]} board
 * @param {string} word
 * @return {boolean}
 */
var exist = function(board, word) {
    const h = board.length, w = board[0].length;
    const directions = [[0, 1], [0, -1], [1, 0], [-1, 0]]; // 下,上 右,左
    const visited = new Array(h);
    for (let i = 0; i < h; ++i) {
        visited[i] = new Array(w).fill(false);
    }
    // 查找函数
    const check = (i, j, s, k) => {
        if (board[i][j] != s.charAt(k)) { // 当前k位置字符就不存在s中
            return false;
        } else if (k == s.length - 1) { // s中的最后一个字符存在
            return true;
        }
        visited[i][j] = true;
        let result = false;
        for (const [dx, dy] of directions) { // 上下左右找
            let newi = i + dx, newj = j + dy;
            if (newi >= 0 && newi < h && newj >= 0 && newj < w) { // 到达边界
                if (!visited[newi][newj]) {
                    const flag = check(newi, newj, s, k + 1); // 往下继续找知道边界
                    if (flag) {
                        result = true;
                        break;
                    }
                }
            }
        }
        visited[i][j] = false; // 没找到
        return result;
    }

    // 开始查找
    for (let i = 0; i < h; i++) {
        for (let j = 0; j < w; j++) {
            const flag = check(i, j, word, 0);
            if (flag) {
                return true;
            }
        }
    }
    return false;
};

复杂度分析

  • 时间复杂度:O(MN⋅3^L),),其中 M,N 为网格的长度与宽度,L 为字符串 word 的长度。在每次调用函数check 时,除了第一次可以进入 4 个分支以外,其余时间我们最多会进入 3个分支(因为每个位置只能使用一次,所以走过来的分支没法走回去)
  • 空间复杂度:O(MN)

引用

  • 剑指offer书籍
  • 力扣题解