【JS每日一算法:剑指Offer系列】🟥184.单词搜索 II(字典树+DFS)

67 阅读2分钟

给定一个 m x n 二维字符网格 board ****和一个单词(字符串)列表 words, 返回所有二维网格上的单词 。

单词必须按照字母顺序,通过 相邻的单元格 内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母在一个单词中不允许被重复使用。

示例 1:

输入: board = [["o","a","a","n"],["e","t","a","e"],["i","h","k","r"],["i","f","l","v"]], words = ["oath","pea","eat","rain"]
输出: ["eat","oath"]

示例 2:

输入: board = [["a","b"],["c","d"]], words = ["abcb"]
输出: []

提示:

  • m == board.length
  • n == board[i].length
  • 1 <= m, n <= 12
  • board[i][j] 是一个小写英文字母
  • 1 <= words.length <= 3 * 104
  • 1 <= words[i].length <= 10
  • words[i] 由小写英文字母组成
  • words 中的所有字符串互不相同

题解:

个人博客

更多JS版本题解点击链接关注该仓库👀

/**
 * @description: 前缀树
 * @author: JunLiangWang
 * @param {*} board 给定矩阵
 * @param {*} words 单词列表
 * @return {*}
 */
function trie(board, words) {
    // 前缀树
    let wordMap = {}
    /**
     * @description: 将字符串转换为前缀树
     * @author: JunLiangWang
     * @param {*} node 当前节点
     * @param {*} str 字符串
     * @param {*} index 索引
     * @return {*}
     */
    function strToMap(node, str, index) {
        // 如果索引超出字符串长度直接return
        if (str.length == index) {
            // 标记当前单词为结尾
            node.end = true
            return
        }
        // 如果树中无该单词则new
        if (node[str[index]] == undefined) node[str[index]] = {}
        // 递归
        strToMap(node[str[index]], str, index + 1)
    }
    // 将单词列表转换为前缀树
    words.forEach((val) => {
        strToMap(wordMap, val, 0)
    })
    // 输出数组
    let outArray = [],
        // 记录已找到的单词
        resultMap = new Map(),
        // 记录已找过的字符
        map = new Array(board.length).fill(0).map(() => new Array(board[0].length).fill(0))
    /**
     * @description: 递归实现dfs
     * @author: JunLiangWang
     * @param {*} node 当前节点
     * @param {*} str  已走过的单词
     * @param {*} i    矩阵横索引
     * @param {*} j    矩阵列索引
     * @return {*}
     */
    function recursion(node, str, i, j) {
        // 当前走到的字符
        let char = board[i][j]
        // 如果该字符在字典树该节点中不存在,
        // 则证明无该单词,直接return
        if (!node[char]) return
        // 如果该节点为end,证明已找到单词
        if (node[char].end) {
            // 如果该单词未找到过,则直接push到结果
            if (!resultMap.get(str + char)) outArray.push(str + char)
            resultMap.set(str + char, true)
        }
        // 标记已走过矩阵该字符
        map[i][j] = 1
        // 左右上下递归
        if (i - 1 >= 0 && map[i - 1][j] == 0) recursion(node[char], str + char, i - 1, j)
        if (i + 1 < board.length && map[i + 1][j] == 0) recursion(node[char], str + char, i + 1, j)
        if (j - 1 >= 0 && map[i][j - 1] == 0) recursion(node[char], str + char, i, j - 1)
        if (j + 1 < board[0].length && map[i][j + 1] == 0) recursion(node[char], str + char, i, j + 1)
        // 重置为未走过
        map[i][j] = 0
    }
    // 遍历执行dfs
    for (let i = 0; i < board.length; i++) {
        for (let j = 0; j < board[i].length; j++) {
            recursion(wordMap, '', i, j)
        }
    }
    // 返回结果
    return outArray
}