题目
给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中,返回 true ;否则,返回 false 。
单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。
示例 1:
输入:board = [[“A”,“B”,“C”,“E”],[“S”,“F”,“C”,“S”],[“A”,“D”,“E”,“E”]], word = “ABCCED”
输出:true
示例 2:
输入:board = [[“A”,“B”,“C”,“E”],[“S”,“F”,“C”,“S”],[“A”,“D”,“E”,“E”]], word = “SEE”
输出:true
示例 3:
输入:board = [[“A”,“B”,“C”,“E”],[“S”,“F”,“C”,“S”],[“A”,“D”,“E”,“E”]], word = “ABCB”
输出:false
class Solution {
public:
bool exist(vector<vector<char>>& board, string word) {
int m=board.size(), n=board[0].size();
vector<vector<bool>> visited(m, vector<bool>(n,false));//记录当前节点是否被访问
//遍历矩阵,判断以每一个节点为起点是否能匹配全部的单词
for(int i=0; i<m; ++i){
for(int j=0; j<n; ++j){
if(dfs(board, visited, word, i, j, 0)) //如果匹配成功,返回true
return true;
}
}
return false;//遍历完矩阵也没找到,就返回false
}
private:
//index表示当前要匹配word的index号字母
bool dfs(vector<vector<char>>& board,vector<vector<bool>>& visited, const string& word, int x, int y, int index){
if(index==word.size()) return true;//如果找到了完整的单词
if(x<0 || y<0 || x>=board.size()||y>=board[0].size()) return false;//如果下标超过矩阵范围
if(visited[x][y]) return false;//如果当前节点已经访问过
if(board[x][y]!=word[index]) return false;//如果匹配失败
//匹配成功
visited[x][y] = true;
//尝试四个方向
bool resu= dfs(board, visited, word, x-1, y, index+1) || dfs(board, visited, word, x+1, y, index+1) || dfs(board, visited, word, x, y-1, index+1) || dfs(board, visited, word, x, y+1, index+1);
visited[x][y] = false;//恢复原样
return resu;//返回结果
}
};
-
时间复杂度O(n^2 *m^2)
-
空间复杂度O(n^2)
-
思路
- 遍历矩阵,以每个点为起点,调用dfs,判断能否找到完全匹配的单词
- dfs传入的参数有原矩阵,记录当前节点是否被访问的visited矩阵,单词word,当前节点的下标x,y以及当前搜索的是单词的第几个字母index
- 递归边界是index等于单词的长度,表示找到了,返回true
- 如果坐标超出矩阵范围,返回false
- 如果当前节点已经被访问过,返回false
- 如果当前节点的值与单词中index对应的字母不匹配,返回false
- 否则,表示当前字母是匹配的,先将visited矩阵中的位置标为true,再递归调用dfs,搜索下一个字母,分别尝试四个方向,将结果记录在resu中
- 将visited矩阵中的位置恢复为false,返回resu
-
优化O(1)的空间复杂度
class Solution {
public:
bool exist(vector<vector<char>>& board, string word) {
int m=board.size(), n=board[0].size();
//优化掉了visited矩阵
for(int i=0; i<m; ++i){
for(int j=0; j<n; ++j){
if(dfs(board, word, i, j, 0))
return true;
}
}
return false;
}
private:
//把0作为标志,如果访问过该节点就将值改为0
bool dfs(vector<vector<char>>& board, const string& word, int x, int y, int index){
if(index==word.size()) return true;
if(x<0 || y<0 || x>=board.size()||y>=board[0].size()) return false;
if(board[x][y]=='0') return false;
if(board[x][y]!=word[index]) return false;
//匹配成功
board[x][y] = '0';
bool resu= dfs(board, word, x-1, y, index+1) || dfs(board, word, x+1, y, index+1) || dfs(board, word, x, y-1, index+1) || dfs(board, word, x, y+1, index+1);
board[x][y] = word[index];//借助index还原原来的单词
return resu;
}
};
- 如果当前节点已经访问过,就将它标记为‘0’,在全字母的矩阵中,如果该节点为1则表示已经访问
- 匹配成功的话,借助word以及index将1再复原为原来的字母
- 从而避免了使用visited矩阵