参考自:《剑指Offer——名企面试官精讲典型编程题》
题目:矩阵中的路径
请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中任意一格开始,每一步可以在矩阵中向左、右、上、下移动一格。如果一条路径经过了矩阵的某一格,那么该路径不能再次进入 该格子。例如在下面的3×4的矩阵中包含一条字符串“BFCE”的路径(路径中的字母用下划线标出)。但矩阵中不包含字符串“ABFB”的路径,因为字符串的第一个字符B占据了矩阵中的第一行第二个格子之后,路径不能再次进入这个格子。
A B T G
C F C S
J D E H
主要思路:使用回溯法,任选一个格子作为路径起点,判断当前格子是否等于字符串第一个字符,相等的话,继续在其左右上下格子中继续查找剩下的字符。若已找到前n个字符,但是在第n个字符对应的格子周围都没有找到第n+1个字符,说明第n个字符对应的格子不满足条件,只能回溯到第n-1个字符,重新定位第n个字符。
关键点:回溯法,二维数组与矩阵
时间复杂度:O(n),n为矩阵元素个数,最坏情况:矩阵中每个元素都查找到字符串长度-1,
public class StringPathInMatrix
{
public static void main(String[] args)
{
//ABTG
//CFCS
//JDEH
//BFCE
String matrix = "ABTGCFCSJDEH";
String str = "BFCE";
boolean result = hasPath(matrix.toCharArray(), 3, 4, str.toCharArray());
System.out.println(result);
}
private static boolean hasPath(char[] matrix, int rows, int cols, char[] str)
{
if (matrix == null || rows <= 0 || cols <= 0 || str == null) return false;
boolean[][] hasVisited = new boolean[rows][cols];
//遍历矩阵所有元素作为起始点,直到找到该字符串路径
for (int row = 0; row < rows; row++)
{
for (int col = 0; col < cols; col++)
{
if (hasStringPath(matrix, rows, cols, row, col, 0, hasVisited, str))
{
return true;
}
}
}
return false;
}
private static boolean hasStringPath(char[] matrix, int rows, int cols, int row, int col,
int pathLength, boolean[][] hasVisted, char[] str)
{
if (pathLength == str.length-1) return true;
boolean hasPath = false;
if (row >= 0 && row < rows && col >= 0 && col < cols &&
!hasVisted[row][col] && matrix[row * cols + col] == str[pathLength])
{
pathLength++;
hasVisted[row][col] = true;
//递归判断左右上下是否存在满足条件的路径
hasPath = hasStringPath(matrix, rows, cols, row, col - 1,
pathLength, hasVisted, str)
|| hasStringPath(matrix, rows, cols, row - 1, col,
pathLength, hasVisted, str)
|| hasStringPath(matrix, rows, cols, row, col + 1,
pathLength, hasVisted, str)
|| hasStringPath(matrix, rows, cols, row + 1, col,
pathLength, hasVisted, str);
//回溯
if (!hasPath)
{
--pathLength;
hasVisted[row][col] = false;
}
}
return hasPath;
}
}