返回

LeetCode 79:在网格中探索单词的深度之旅

前端

深度优先搜索:探索网格中的单词世界

导言

在计算机科学领域,算法是解决复杂问题的有力工具。LeetCode 79:单词搜索就是这样一项经典挑战,它要求我们在网格中找到一个给定单词。为了解决这个问题,我们将深入探讨一种称为深度优先搜索(DFS)的强大算法。

深度优先搜索:沿着路径前进

DFS 是一种搜索算法,它通过沿着一系列路径深入搜索网格,直到无法再前进为止。如果我们想象一下自己在一座迷宫中,DFS 就像一条沿着一条走廊探索,直到走到尽头,然后回过头来尝试另一条走廊。

回溯:纠正错误的尝试

在 DFS 过程中,我们可能会发现一条路径不通往单词的终点。这就是回溯发挥作用的地方。回溯允许我们返回到最近的有效单元格,然后从那里继续探索。这种策略确保我们不会在死胡同上浪费时间,并帮助我们找到单词存在的所有可能路径。

算法的步骤:细致入微的探索

  1. 初始化: 标记已访问单元格。
  2. 遍历网格: 检查每个单元格,寻找单词第一个字母的匹配项。
  3. DFS 函数: 从匹配单元格递归搜索,检查后续字母匹配情况。
  4. 回溯: 如果匹配失败,返回到最近的有效单元格继续探索。
  5. 重复: 直到单词被找到或搜索结束。

代码实现:让算法焕发生机

const exist = (board, word) => {
  // 初始化已访问单元格数组
  const visited = new Array(board.length).fill(false).map(() => new Array(board[0].length).fill(false));

  // 遍历网格,寻找单词第一个字母的匹配项
  for (let i = 0; i < board.length; i++) {
    for (let j = 0; j < board[0].length; j++) {
      if (board[i][j] === word[0] && dfs(i, j, 0)) {
        return true;
      }
    }
  }

  // DFS 函数:从匹配单元格递归搜索
  function dfs(i, j, index) {
    // 边界条件:超出网格范围或已访问单元格
    if (i < 0 || i >= board.length || j < 0 || j >= board[0].length || visited[i][j] || board[i][j] !== word[index]) {
      return false;
    }

    // 找到单词最后一个字母
    if (index === word.length - 1) {
      return true;
    }

    // 标记当前单元格已访问
    visited[i][j] = true;

    // 递归搜索相邻单元格
    const result =
      dfs(i + 1, j, index + 1) ||
      dfs(i - 1, j, index + 1) ||
      dfs(i, j + 1, index + 1) ||
      dfs(i, j - 1, index + 1);

    // 搜索完成,标记当前单元格未访问
    visited[i][j] = false;

    // 返回搜索结果
    return result;
  }

  // 单词未找到
  return false;
};

结语:在网格中寻找单词的艺术

LeetCode 79:单词搜索是一个算法难题,需要我们应用 DFS 算法和回溯策略。通过了解这些概念并应用提供的代码示例,我们可以高效地在网格中找到单词,深入探索计算机科学的奥秘。

常见问题解答

  1. DFS 和 BFS 有什么区别?
    DFS 深入探索一条路径,而 BFS 广度优先搜索所有可能的路径。

  2. 回溯在 DFS 中的作用是什么?
    回溯允许我们纠正错误的尝试并探索其他可能的路径。

  3. 算法时间复杂度是多少?
    O(mn * 4^L),其中 m 和 n 是网格大小,L 是单词长度。

  4. 如何优化算法性能?
    使用备忘录或剪枝技术来减少重复的搜索。

  5. DFS 算法还可以应用于哪些问题?
    DFS 可用于解决迷宫求解、图遍历和回路检测等问题。