题目
请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵的任意一格开始,每一步可以在矩阵中向左、右、上、下移动一格。如果一条路径经过了矩阵的某一格,那么该路径不能再次进入该格子。例如,在下面的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书籍
- 力扣题解