0%

剑指offer012矩阵中的路径

Problem:

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

Intuition:

使用回溯法(backtracking)进行求解,它是一种暴力搜索方法,通过搜索所有可能的结果来求解问题。回溯法在一次搜索结束时需要进行回溯(回退),将这一次搜索过程中设置的状态进行清除,从而开始一次新的搜索过程。在这一题中我们要做的是额外用一个数组来记录矩阵中的点是否被访问过的状态。
个人理解回溯法主要适用于程序需要你进行尝试的情况。那么我们在尝试一步后会修改某些状态,那么在尝试不成功的时候要注意对这些状态进行复原。这个过程颇类似于函数调用的时候对程序上下文进行压栈的情况。

Solution:

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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
public class CodingInterview_012 {
//这一题的重点是要把握好要有一个visited数组来记录哪些地方已经走过。已经走过的点不能被重新访问
public static boolean hasPath(char[] matrix, int rows, int cols, char[] str) {
// 参数校验
if (matrix == null || matrix.length != rows * cols || str == null || str.length < 1) {
return false;
}

// 变量初始化
boolean[] visited = new boolean[rows * cols];
for (int i = 0; i < visited.length; i++) {
visited[i] = false;
}

// 记录结果的数组,
int pathLength = 0;
// 以每一个点为起始进行搜索
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
if (hasPathCore(matrix, rows, cols, str, visited, i, j, pathLength)) {
return true;
}
}
}

return false;
}

/**
* 回溯搜索算法
*
* @param matrix 输入矩阵
* @param rows 矩阵行数
* @param cols 矩阵列数
* @param str 要搜索的字符串
* @param visited 访问标记数组
* @param row 当前处理的行号
* @param col 当前处理的列号
* @param pathLength 已经处理的str中字符个数
* @return 是否找到 true是,false否
*/
private static boolean hasPathCore(char[] matrix, int rows, int cols, char[] str, boolean[] visited,
int row, int col, int pathLength) {

if (pathLength == str.length) {
return true;
}

boolean hasPath = false;

// 前面两个条件判断位置是否合法
//第三个条件判断矩阵位置的当前字符是否与字符串中对应位置的字符一致
//第四个条件是重点,我们要看这个矩阵位置上的字符是否已经被访问过。
if (row >= 0 && row < rows
&& col >= 0 && col < cols
&& matrix[row * cols + col] == str[pathLength]
&& !visited[row * cols + col]) {
//跑到这里说明当前矩阵中的字符与字符串对应位置的字符一致,那么我们就把visit状态置为true,但是此时并不能说明就一定成功,还要看后面的字符能不能满足,
//一旦不满足还要重新置回false.
visited[row * cols + col] = true;
pathLength++;

// 按左上右下进行回溯
hasPath = hasPathCore(matrix, rows, cols, str, visited, row, col - 1, pathLength)
|| hasPathCore(matrix, rows, cols, str, visited, row - 1, col, pathLength)
|| hasPathCore(matrix, rows, cols, str, visited, row, col + 1, pathLength)
|| hasPathCore(matrix, rows, cols, str, visited, row + 1, col, pathLength);

if (!hasPath) {
//程序执行到了这里就说明当前这个点已经走不通了,需要把它的visit状态重新置回false.
pathLength--;
visited[row * cols + col] = false;
}

}

return hasPath;
}

}