LeetCode 79.单词搜索 - JavaScript(深度优先遍历 + 回溯)

1,328 阅读2分钟

这是我参与8月更文挑战的第18天,活动详情查看:8月更文挑战


说明:文章部分内容及图片出自网络,如有侵权请与我本人联系(主页有公众号:小攻城狮学前端)

作者:小只前端攻城狮、 主页:小只前端攻城狮的主页、 来源:掘金

GitHub:P-J27、 CSDN:PJ想做前端攻城狮

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。


LeetCode 79.单词搜索 - JavaScript

题目描述

给定一个二维网格和一个单词,找出该单词是否存在于网格中。

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

例子:

board = [ ['A','B','C','E'], ['S','F','C','S'], ['A','D','E','E'] ]

给定 word = "ABCCED", 返回 true. 给定 word = "SEE", 返回 true. 给定 word = "ABCB", 返回 false.


解法:深度优先遍历 + 回溯

准备两个函数exist()__exist()

exist() 用于循环遍历网格,当前元素等于单词的第一个字母时,进入 __exist() 函数。代码实现如下:


var exist = function(board, word) {
  const rowNum = board.length;
  const colNum = board[0].length;

  for (let i = 0; i < rowNum; ++i) {
    for (let j = 0; j < colNum; ++j) {
      if (board[i][j] === word[0]) {
        const isExist = __exist(board, word, i, j, {});
        if (isExist) return true; // 找到就返回
      }
    }
  }
  return false;
};

__exist() 函数是从指定位置开始,按照“上下左右”四个方向递归遍历,直到找到或者找不到所有匹配的字母为止。代码实现如下:


function __exist(board, word, row, col, visited) {
  // 单词中字母全部匹配,说明可以搜索到,返回true
  if (!word.length) {
    return true;
  }

  const key = `${row}-${col}`;
  // 越界、之前访问过、单词首字母和当前元素不相同,返回false
  if (
    row >= board.length ||
    row < 0 ||
    col >= board[0].length ||
    col < 0 ||
    visited[key] ||
    board[row][col] !== word[0]
  ) {
    return false;
  }

  visited[key] = true;
  word = word.slice(1);
  // 下、上、右、左搜索(顺序不重要)
  const success =
    __exist(board, word, row + 1, col, visited) ||
    __exist(board, word, row - 1, col, visited) ||
    __exist(board, word, row, col + 1, visited) ||
    __exist(board, word, row, col - 1, visited);

  // success为false时,就是回溯
  visited[key] = success;
  return success;
}

代码中如果 success 为 false,说明以当前元素为出发点,搜索剩余字母失败。那么应该将visited[key]重置为 false,以方面其他路径使用。

例如对于以下数组,要搜索abbcbd。按照代码里的方向搜索逻辑,会先找到 abbd,然后发现查找失败,此时就要回溯。否则当按照正确方向找来时,visited 中的值是错误的。

a b b
d b c

感谢阅读,希望能对你有所帮助,文章若有错误或者侵权,可以在评论区留言或在我的主页添加公众号联系我。

写作不易,如果觉得不错,可以「点赞」+「评论」 谢谢支持❤