矩阵中的路径
题目描述:请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向上,向下移动一个格子。如果一条路径经过了矩阵中的某一个格子,则该路径不能再进入该格子。
例如:[ [a b c e]
[s f c s]
[a d e e] ]
矩阵中包含一条字符串 “bcced” 的路径,但是矩阵中不包含 "abcb" 路径,因为字符串的第一个字符 b 占据了矩阵中的第一行第二个格子之后,路径不能再次进入该格子。
分析:在力扣上看到一个我可以理解的题解,但是还不会实现,先把思路放在这。
1. 既然要在矩阵中匹配一个单词 word,那么我们自然地想到,应该先遍历矩阵找到单词的开头。
2. 找到开头后,有必要深入下去尝试匹配剩余字符。
3. 深入匹配有 4 个方向可以选择,只要有 1 个方向匹配成功了,就说明找到了;只有 4 个方向都无法匹配出 word,才说明这个开头不合适,应该继续遍历矩阵找新的开头。
4. 找到新的开头,继续重复以上匹配过程。
5. 由于匹配过程不能使用已经用过的字符,所以应当标记匹配过的字符。原始的想法是借助一个和 board 同样大小的矩阵 boolean[][] visit = new boolean[r][c],r 表示 board 的行数,c 表示 board 的列数;
但是我们可以通过巧妙的方法,避免这个空间开销。具体方法是,如果我们已经访问过这个字符,那么先把这个字符赋值为一个矩阵中不可能存在的字符,比如 '#',就可以表示已访问过了。当这条路走不通了,恢复它本来的样子就可以了。(当然必须说明,这种取巧方法是靠运气的,因为题目并没有说明矩阵中字符的种类,只是恰好用到了一个测试案例里没有的字符作为标记)为什么要恢复本来的样子?因为当前路走不通,只是因为开头不对。找到新的开头后,以前旧的开头访问过的字符对于新开头来说仍然是可以访问的。比如说,在以下矩阵匹配 word = "aabc"。
word = "abc" board = [ ['a', 'a'], ['c', 'b'] ] 第一次从(0,0)开始匹配,标记为已访问 board = [ ['#', 'a'], ['c', 'b'] ] 由于4个方向都不能匹配完 word,因此从这个开头出发是匹配不出 word 的,删除标记,恢复本来的样子 board = [ ['a', 'a'], ['c', 'b'] ] 第二次从(0,1)开始匹配,是可以匹配出 "aacb" 的:(0,1) -> (0,0) -> (1,0) -> (1,1) 如果第一次匹配没有撤销标记,那么(0,0)位置上是'#'是不可走的,这将导致第二次匹配失败,而理应是成功的
1 public class Solution { 2 public boolean hasPath(char[] matrix, int rows, int cols, char[] str){ 3 int[] flag = new int[rows * cols]; 4 for(int i = 0; i < rows; i++) { 5 for(int j = 0; j < cols; j++) { 6 if(help(matrix, rows, cols, str, 0, flag, i, j)) { 7 return true; 8 } 9 } 10 } 11 12 return false; 13 } 14 public boolean help(char[] matrix, int rows, int cols, char[] str, int cur, int[] flag, int r, int c){ 15 // int row, int col 表明当前的坐标的行列值 16 // flag 表明那些曾经在路径中出现过的节点的坐标 17 // cur 表示当前需要匹配的字符的位置,是下一个待访问的节点,不需关系其有效性,因为最后一个元素是‘、0’ 18 int index = cols * r + c; 19 if (r >= 0 && r < rows && c >= 0 && c < cols && flag[index] == 0) { 20 if (matrix[index] == str[cur]) { 21 cur = cur + 1; 22 if (cur >= str.length) return true; 23 flag[index] = 1; 24 if (help(matrix, rows, cols, str, cur, flag, r - 1, c) || 25 help(matrix, rows, cols, str, cur, flag, r + 1, c) || 26 help(matrix, rows, cols, str, cur, flag, r, c - 1) || 27 help(matrix, rows, cols, str, cur, flag, r, c + 1)) 28 return true; 29 flag[index] = 0; 30 return false; 31 } 32 return false; 33 } 34 return false; 35 } 36 }