这个系列没啥花头,就是纯 leetcode 题目拆解分析,不求用骚气的一行或者小众取巧解法,而是用清晰的代码和足够简单的思路帮你理清题意。让你在面试中再也不怕算法笔试。
56. 单词搜索 (word-search)
标签
- DFS + 回溯
- 中等
题目
这里不贴题了,leetcode打开就行,题目大意:
给定一个二维网格和一个单词,找出该单词是否存在于网格中。其实就是找个字符路径
单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用(所以要记录visited)。
示例:
board =
[
['A','B','C','E'],
['S','F','C','S'],
['A','D','E','E']
]
board =
[
['A','B','C','E'],
['S','F','C',('S')],
['A','D',('E'),('E')] => SEE => true
]
给定 word = "ABCCED", 返回 true
给定 word = "SEE", 返回 true
给定 word = "ABCB", 返回 false
相关知识
组合问题,可以用回溯法:如果不了解,请移步这篇 回溯思想
非常类似的问题这个是之前的问题,非常的类似。
基本思路
- 我觉的这题看下面的代码注释已经非常清晰明了,重点在于对四个方向上的DFS。
- 答疑几个点:
- visited 数组作用,记录下已经访问过的位置,以免
路径重合 - 判断走的步骤之后是否越界是本题的
边界条件,说明是在内部走动,形成路径。 - 深刻理解
DFS + 回溯类型的问题之后,你会类比之前好多题做到触类旁通。
写法实现
var exist = function(board, word) {
// 获取矩阵行、列数 和字符串 length
const [row, col, wordLen] = [board.length, board[0].length, word.length]
// 取四个方向上走的方式 (i, j)坐标 往上走就是 i - 1 =>对应 [-1, 0]
// 右 左 上 下
const stepDicts = [[0, 1], [0, -1], [1, 0], [-1, 0]]
// 声明已经访问过的路径,初始化所有元素为 false (可以理解为之前问题的 curUsed)
const visited = new Array(row).fill(0).map(it => new Array(col).fill(false));
// 下面我们回顾 DFS ,搜索正确路径
let dfs = (i, j, curIndex) => {
// 如果当前位置正是需要搜的当前元素,且 curIndex已经是需要找的最后一个元素,直接返回 true
if (board[i][j] === word.charAt(curIndex) && curIndex === wordLen - 1) {
return true
}
// 如果当前位置不等于我们需要搜的当前串的 curIndex 的元素,返回false
if (board[i][j] !== word.charAt(curIndex)) {
return false
}
// 走到这步之后该位置存入visited,表示已经访问过,要不绕圈回到原点就有问题了
visited[i][j] = true
let res = false;
// 分别往4个方向上试
for (const [dx, dy] of stepDicts) {
// 新的 i, j 就是往各自方向上加
let newi = i + dx, newj = j + dy;
// 这四个方向走完之后,还在范围之内,没有越出边界
if (newi >= 0 && newi < row && newj >= 0 && newj < col) {
// 而且并不是之前走过的路径
if (!visited[newi][newj]) {
// 那么我们就继续往下走一步,进行递归
if (dfs(newi, newj, curIndex + 1)) {
res = true;
break;
}
}
}
}
// 回溯一步
visited[i][j] = false;
return res;
}
// 遍历这个二维数组,寻找起始点,有起始点的话进行DFS
for (let i = 0; i < row; i++) {
for (let j = 0; j < col; j++) {
// 位置元素是起始点元素
if (board[i][j] === word[0] && dfs(i, j, 0)) {
return true
}
}
}
return false
};
let board = [
["A","B","C","E"],
["S","F","C","S"],
["A","D","E","E"]]
console.log(exist(board, 'SEE'))
另外向大家着重推荐下这位大哥的文章,非常深入浅出,对前端进阶的同学非常有作用,墙裂推荐!!!核心概念和算法拆解系列
今天就到这儿,想跟我一起刷题的小伙伴可以加我微信哦
搜索我的微信号infinity_9368,可以聊天说地
加我暗号 "天王盖地虎" 下一句的英文,验证消息请发给我
presious tower shock the rever monster,我看到就通过,暗号对不上不加哈,加了之后我会尽我所能帮你,但是注意提问方式,建议先看这篇文章:提问的智慧