一、题目
给定一个 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
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/word-search
二、思路
主要思路就是循环遍历每个数组中的每个字符,若当前字符和给定字符串的第一个字符相同,则从该位置的字符开始向四个方向进行深度优先遍历,和给定字符串的下一个字符相比较,若有一个方向能查找到和给出的字符串相同的串,则返回true,若四个方向都搜索不到匹配的串,则继续数组中的下一个字符,重复上述深度优先搜索操作,若直至最后数组最后一个字符都搜索不到匹配的串,则返回false。
在遍历字符过程中,需要定义一个同样大小的数组标记某个位置的元素在本次深度搜索的过程中是否访问过(每个位置的字符不能重复使用),0表示还未访问过,1表示已经访问过,每访问一个字符,则将对应位置的值置为1,若该位置的四个方向都无法搜索到匹配的串,回溯到该位置时将该位置的值重新置为0,表示之后可以继续访问这个位置对应的字符。
三、代码
class Solution {
int row, col;
public:
bool exist(vector<vector<char>>& board, string word) {
int wlen = word.size();
if(wlen == 0) return true;
row = board.size(); //行数
col = board[0].size(); //列数
vector<vector<int>> v(row, vector<int>(col, 0)); //记录该位置元素是否访问过
for(int i=0; i<row; i++){
for(int j=0; j<col; j++){
bool flag = dfs(board, word, 0, i, j, v);
if(flag == true) return true;
}
}
return false;
}
//index表示word中第几个字母, i,j表示board中的下标, v中的元素标识是否访问过
bool dfs(vector<vector<char>>& board, string& word, int index, int i, int j, vector<vector<int>>& v){
if(i<0 || j< 0 || i>=row || j>=col || v[i][j] == 1 || board[i][j] != word[index]){
return false;
}
if(index == word.size()-1){
return true;
}
v[i][j] = 1;
bool result = false;
vector<pair<int, int>> directions {{1,0}, {-1,0}, {0,-1}, {0,1}};
for(auto dir: directions){ //分别向四个方向进行深搜
int newi = i + dir.first, newj = j + dir.second;
bool flag = dfs(board, word, index+1, newi, newj, v);
if(flag){
result = true;
break;
}
}
v[i][j] = 0; //查找失败,回溯到该位置
return result;
}
};