VIRTUALS

the virtual labs for the virtuals

0%

剑指Offer 12. 矩阵中的路径

摘要:
回溯算法经典题。

题目

请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一格开始,每一步可以在矩阵中向左、右、上、下移动一格。如果一条路径经过了矩阵的某一格,那么该路径不能再次进入该格子。例如,在下面的3×4的矩阵中包含一条字符串“bfce”的路径(路径中的字母用加粗标出)。

[[“a”,” b “,”c”,”e”],
[“s”,” f “,” c “,”s”],
[“a”,”d”,” e “,”e”]]

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

示例 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

提示:

  • $1 <= board.length <= 200$
  • $1 <= board[i].length <= 200$

回溯

本题与 单词搜索 完全相同。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
// 执行用时: 44 ms
// 内存消耗: 11.1 MB
class Solution {
public:
vector<vector<char>> b;
vector<vector<bool>> st;
int m, n;
string w;
int len;
const int dr[4] = {-1, 0, 1, 0}, dc[4] = {0, 1, 0, -1};
bool exist(vector<vector<char>>& board, string word) {
b = board, w = word;
m = b.size(), n = b[0].size();
len = word.size();
st = vector<vector<bool>> (m, vector<bool>(n, false));

for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (b[i][j] == w[0]) {
if (dfs(i, j, 0)) return true;
}
}
}

return false;
}

bool dfs(int r, int c, int u) {
if (b[r][c] != w[u]) {
return false;
}
if (u == len - 1) {
return true;
}
// 正确的节点
st[r][c] = true;

for (int d = 0; d < 4; d++) {
int ner = r + dr[d], nec = c + dc[d];
if (ner >= 0 && ner < m && nec >= 0 && nec < n && !st[ner][nec]) {
if (dfs(ner, nec, u + 1)) return true;
}
}
// 恢复现场
st[r][c] = false;
return false;
}
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
// 执行用时: 7 ms
// 内存消耗: 40.1 MB
class Solution {
char[][] b;
String w;
int m, n;
int len;
int[] dr, dc;
boolean[][] st;
public boolean exist(char[][] board, String word) {
b = board;
w = word;
m = b.length;
n = b[0].length;
len = w.length();
dr = new int[] {-1, 0, 1, 0};
dc = new int[] {0, 1, 0, -1};
st = new boolean[m][n];

for (int i = 0; i < m; i++) {
Arrays.fill(st[i], false);
}

for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (b[i][j] == w.charAt(0)) {
if (dfs(i, j, 0)) return true;
}
}
}

return false;
}

private boolean dfs(int r, int c, int u) {
if (b[r][c] != w.charAt(u)) return false;
if (u == len - 1) return true;
// else keep checking
st[r][c] = true;

for (int d = 0; d < 4; d ++) {
int ner = r + dr[d], nec = c + dc[d];
if (ner >= 0 && ner < m && nec >= 0 && nec < n && !st[ner][nec]) {
if (dfs(ner, nec, u + 1)) return true;
}
}
st[r][c] = false;
return false;
}
}