字母从任意位置出发移动,不能重复移动,若能构成单词,则true,否则返回false。示例:
给定map=[[a d c],
(资料图片)
[f e d],
[g n m]
]; 若string为fedc则true;若gnme则false。
解题思想:以每一个字母为出发点,向四周遍历,若不符合单词,则返回false,否则继续遍历,直到达到单词长度,则返回true。
先建立一个字母检测函数,再对数组中的每一个字母进行检测,若通过则直接返回true
检测函数需要告诉我们这个字母为起点是否可以搜索到单词,故为bool类型,不可以走回头路,所有需要建立一个等大小二维数组记录移动过的位置,若遍历至该位置,则直接跳出。
以下为代码分析:
遍历函数:
bool exist(vector<vector<char>>& board, string word) { 输入参数为字母数组和目标单词
int h = board.size(), w = board[0].size(); h为二维数组的行数,w为列数
vector<vector<int>> visited(h, vector<int>(w)); 建立一个等大的visited矩阵,防止重复
for (int i = 0; i < h; i++) {
for (int j = 0; j < w; j++) { 2重循环遍历数组每个元素
bool flag = check(board, visited, i, j, word, 0); 传入两个二维数组,当前字母坐标
if (flag) {
return true; 如果在某次遍历中获得了true的结果,则word被找到,返回true
}
}
}
return false; 如果遍历完所有字母仍未找到,则意味着没有,返回false
}
字母检测函数:
bool check(vector<vector<char>>& board, vector<vector<int>>& visited, int i, int j, string& s, int k) { k为单词字符串下标,用来索引单词字母
if (board[i][j] != s[k]) {
return false; 如果首字母都对不上,直接false,去查下一个字母起点
} else if (k == s.length() - 1) {
return true; 校对完了单词的所有字母都有对应,则单词被找到,返回true
}
visited[i][j] = true; 重置参数,当前字母位置被拜访,标记为true
vector<pair<int, int>> directions{{0, 1}, {0, -1}, {1, 0}, {-1, 0}}; 可以对上下左右查找
bool result = false; 重置参数,查找结果默认为没找到
for (const auto& dir: directions) { 对4个方向分别进行查找
int newi = i + dir.first, newj = j + dir.second; 更新查找坐标,进行“移动”
if (newi >= 0 && newi < board.size() && newj >= 0 && newj < board[0].size())确认新的移动到的位置没有越界,若越界则重新进行移动
{
if (!visited[newi][newj]) {
bool flag = check(board, visited, newi, newj, s, k + 1); 若移动到的新位置被拜访过,则直接跳过,重新移动。若移动到的新位置没被拜访过,则进行迭代,单词下标索引加1,以这个新位置为首字母继续向下检测,若返回错误,则返回循环,继续移动剩下的次数,若都错误,则该字母查找失败,给该字母ij重置为未拜访,以下一个字母为起点进行新的一轮查找。若返回正确,则意味着找出整个单词,跳出那层函数并赋值给flag,跳出循环,返回true,进而让遍历函数知道这个首字母找到了完整单词,返回为真,任务结束。(核心)
if (flag) {
result = true; flag为
break;
}
}
}
}
visited[i][j] = false;
return result;
}
代码最好结合着实例一起看,会比较容易理解。
源码链接:https://leetcode.cn/problems/word-search/solution/dan-ci-sou-suo-by-leetcode-solution/