前言
这道题我折腾了一个半~两个小时,终于AC了,特此纪念.
题目描述
给定一个 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 仅由大小写英文字母组成
注意:本题与主站 79 题相同:https://leetcode-cn.com/problems/word-search/
通过次数193,140提交次数426,673描述
思路
老样子,递归三部曲:
返回逻辑:当前index(size)下的字符和word[index]下的字符不一样,或者已经找到了满足条件的情况.
处理逻辑:设置访问位为true,同时往字符串中push_back(),如果两个字符串相等,就使得flag=1,返回,如果字符串长度不等,再向四周DFS.最后再回溯使得str.pop_back(),vis[i][j]=false;
返回值:void
代码
class Solution {
public:
int m, n;
int a[4] = {-1,1,0,0}; //行,上下左右
int b[4] = {0,0,-1,1}; //列,上下左右
int flag = 0;
int len;
bool equal(string& str1, string& str2) {
int size1 = str1.size();
int size2 = str2.size();
if (size1 != size2) return false;
for (int i = 0; i < size1; ++i) {
if (str1[i] != str2[i]) return false;
}
return true;
}
void dfs(int i, int j, vector<vector<char>>& board, string word, vector<vector<bool>>& vis,string& str,int size) {
if (flag) return;
str.push_back(board[i][j]);
vis[i][j] = true;
if (str[size] != word[size]) {
str.pop_back();
vis[i][j] = false;
return;
}
if (size==len-1) {
if (equal(str, word)) {
flag = 1;
return;
}
else {
str.pop_back();
vis[i][j] = false;
return;
}
}
for (int k = 0; k < 4; ++k) {
int x = i + a[k];
int y = j + b[k];
if (x < 0 || y < 0 || x >= m || y >= n || vis[x][y]) continue;
dfs(x, y, board, word, vis, str,size+1);
}
str.pop_back();
vis[i][j] = false;
}
bool exist(vector<vector<char>>& board, string word) {
m = board.size();
n = board[0].size();
vector<vector<bool>> vis(m, vector<bool>(n, false));
string str;
len = word.size();
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
if (flag) return true;
dfs(i, j, board, word, vis, str,0);
}
}
if (flag) return true;
return false;
}
};
小结
回溯法虽然有模板,但是还是因为逻辑条件较复杂导致的考虑不周全而总是出错,我们还是需要多多动手实践,遇到不会的地方,一步一步调试,把有觉得有问题的变量都打印下来,不仅锻炼了逻辑思维还锻炼了DEBUG能力.