1. 题目来源
链接:矩阵中的路径
来源:LeetCode——《剑指-Offer》专项
2. 题目说明
请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一格开始,每一步可以在矩阵中向左、右、上、下移动一格。如果一条路径经过了矩阵的某一格,那么该路径不能再次进入该格子。例如,在下面的 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
3. 题目解析
方法一:DFS、回溯、bool矩阵、经典仿照原书
典型 DFS
应用,也就是回溯法,主要以下几点思路:
- 创建一个和原数组等大小的
bool
型visited
数组用来记录当前位置是否已经被访问过,在这里一维vector
即可,根据坐标关系能够映射为二维坐标中 - 如果二维数组
board
的当前字符和目标字符串word
对应的字符相等,则对其上下左右四个邻字符分别调用DFS
的递归函数,只要有一个返回true
,那么就表示可以找到对应的字符串,返回true
即可 - 当遍历完
board
还没找到即返回false
参见代码如下:
// 执行用时 :12 ms, 在所有 C++ 提交中击败了18.23%的用户
// 内存消耗 :10.6 MB, 在所有 C++ 提交中击败了100.00%的用户
class Solution {
public:
int movingCount(int m, int n, int k) {
int tmp = m * n;
vector<bool> visited(tmp, false);
int count = movingCountCore(m, n, k, 0, 0, visited);
return count;
}
int movingCountCore(int m, int n, int k, int row, int col, vector<bool>& visited) {
int count = 0;
if (check(m, n, k, row, col, visited)) {
visited[row * n + col] = true;
count = 1 + movingCountCore(m, n, k, row - 1, col, visited)
+ movingCountCore(m, n, k, row, col - 1, visited)
+ movingCountCore(m, n, k, row + 1, col, visited)
+ movingCountCore(m, n, k, row, col + 1, visited);
}
return count;
}
bool check(int m, int n, int k, int row, int col, vector<bool>& visited) {
if (row >= 0 && row < m && col >= 0 && col < n
&& getDigitSum(row) + getDigitSum(col) <= k
&& !visited[row * n + col])
return true;
return false;
}
int getDigitSum(int number) {
int sum = 0;
while (number > 0) {
sum += number % 10;
number /= 10;
}
return sum;
}
};
方法二:DFS、回溯、修改原数组
还有一种选择,即可以不用 visited
数组,直接对 board
数组进行修改,将其遍历过的位置改为特定符号,记得递归调用完后需要恢复之前的状态,也是一个常见的优化技巧
参见代码如下:
// 执行用时 :12 ms, 在所有 C++ 提交中击败了18.23%的用户
// 内存消耗 :10.6 MB, 在所有 C++ 提交中击败了100.00%的用户
class Solution {
public:
bool exist(vector<vector<char>>& board, string word) {
if (board.empty() || board[0].empty())
return false;
int m = board.size(), n = board[0].size();
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
if (search(board, word, 0, i, j))
return true;
}
}
return false;
}
bool search(vector<vector<char>>& board, string word, int idx, int i, int j) {
if (idx == word.size())
return true;
int m = board.size(), n = board[0].size();
if (i < 0 || j < 0 || i >= m || j >= n || board[i][j] != word[idx])
return false;
char c = board[i][j];
board[i][j] = '#';
bool res = search(board, word, idx + 1, i - 1, j)
|| search(board, word, idx + 1, i + 1, j)
|| search(board, word, idx + 1, i, j - 1)
|| search(board, word, idx + 1, i, j + 1);
board[i][j] = c;
return res;
}
};