这是我参与11月更文挑战的第8天,活动详情查看:2021最后一次更文挑战
矩阵中的路径
给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中,返回 true ;否则,返回 false 。
单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。
例如,在下面的 3×4 的矩阵中包含单词 "ABCCED"(单词中的字母已标出)。
示例 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 board 和 word 仅由大小写英文字母组成
题解
方法一:深度优先遍历——Java
本问题是典型的矩阵搜索问题,可使用 深度优先搜索(DFS)+ 剪枝 解决。
-
深度优先搜索: 可以理解为暴力法遍历矩阵中所有字符串可能性。DFS 通过递归,先朝一个方向搜到底,再回溯至上个节点,沿另一个方向搜索,以此类推。
-
剪枝: 在搜索中,遇到 这条路不可能和目标字符串匹配成功 的情况(例如:此矩阵元素和目标字符不同、此元素已被访问),则应立即返回,称之为 可行性剪枝 。
class Solution {
public static boolean exist(char[][] board, String word) {
int row = board.length;
int column = board[0].length;
boolean[][] visited = new boolean[row][column];
char[] words = word.toCharArray();
for (int i = 0; i < row; i++) {
for (int j = 0; j < column; j++) {
if (existHelp(board, words, visited, i, j, 0)) {
return true;
}
}
}
return false;
}
private static boolean existHelp(char[][] board, char[] words, boolean[][] visited,
int i, int j, int k) {
if (i < 0 || i >= board.length || j < 0 || j >= board[0].length ||
visited[i][j] || board[i][j] != words[k]) {
return false;
}
if (k == words.length - 1) {
return true;
}
visited[i][j] = true;
boolean res = existHelp(board, words, visited, i + 1, j, k + 1) ||
existHelp(board, words, visited, i - 1, j, k + 1) ||
existHelp(board, words, visited, i, j + 1, k + 1) ||
existHelp(board, words, visited, i, j - 1, k + 1);
visited[i][j] = false;
return res;
}
}
时间复杂度:O(3^K * MN) 空间复杂度:O(K)
方法一:深度优先遍历——Go
func exist(board [][]byte, word string) bool {
words, m, n:= []byte(word), len(board), len(board[0])
for i:=0; i<m; i++{
for j:=0; j<n; j++{
if board[i][j] == words[0]{ // 寻找到匹配的第一个字符
if search(i, j, board, words){
return true
}
}
}
}
return false
}
func search (i, j int, board [][]byte, words []byte) bool {
m, n := len(board), len(board[0])
if i < 0 || i >= m || j < 0 || j >=n || board[i][j] != words[0]{
// 不符合的条件,索引越界和字符不等
return false
}
if len(words) == 1{
// 匹配成功, 返回true
return true
}
tmp := board[i][j]
board[i][j] = '1' // 由于words只能是字母,所以'1'不会被匹配
// 递归回溯
if search(i+1, j, board, words[1:]) || search(i, j+1, board, words[1:]) || search(i-1, j, board, words[1:]) || search(i, j-1, board, words[1:]){
return true
}else{
//注意由于board是slice引用类型,所以函数的修改会真正的修改原slice的值,所以需要重新改正回来
board[i][j] = tmp
return false
}
}