返回介绍

solution / 0000-0099 / 0079.Word Search / README

发布于 2024-06-17 01:04:39 字数 9724 浏览 0 评论 0 收藏 0

79. 单词搜索

English Version

题目描述

给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中,返回 true ;否则,返回 false

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

 

示例 1:

输入:board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "ABCCED"
输出:true

示例 2:

输入:board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "SEE"
输出:true

示例 3:

输入:board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "ABCB"
输出:false

 

提示:

  • m == board.length
  • n = board[i].length
  • 1 <= m, n <= 6
  • 1 <= word.length <= 15
  • boardword 仅由大小写英文字母组成

 

进阶:你可以使用搜索剪枝的技术来优化解决方案,使其在 board 更大的情况下可以更快解决问题?

解法

方法一:DFS(回溯)

我们可以枚举网格的每一个位置 $(i, j)$ 作为搜索的起点,然后从起点开始进行深度优先搜索,如果可以搜索到单词的末尾,就说明单词存在,否则说明单词不存在。

因此,我们设计一个函数 $dfs(i, j, k)$,表示从网格的 $(i, j)$ 位置出发,且从单词的第 $k$ 个字符开始搜索,是否能够搜索成功。函数 $dfs(i, j, k)$ 的执行步骤如下:

  • 如果 $k = |word|-1$,说明已经搜索到单词的最后一个字符,此时只需要判断网格 $(i, j)$ 位置的字符是否等于 $word[k]$,如果相等则说明单词存在,否则说明单词不存在。无论单词是否存在,都无需继续往下搜索,因此直接返回结果。
  • 否则,如果 $word[k]$ 字符不等于网格 $(i, j)$ 位置的字符,说明本次搜索失败,直接返回 false
  • 否则,我们将网格 $(i, j)$ 位置的字符暂存于 $c$ 中,然后将此位置的字符修改为一个特殊字符 '0',代表此位置的字符已经被使用过,防止之后搜索时重复使用。然后我们从 $(i, j)$ 位置的上、下、左、右四个方向分别出发,去搜索网格中第 $k+1$ 个字符,如果四个方向有任何一个方向搜索成功,就说明搜索成功,否则说明搜索失败,此时我们需要还原网格 $(i, j)$ 位置的字符,即把 $c$ 放回网格 $(i, j)$ 位置(回溯)。

在主函数中,我们枚举网格中的每一个位置 $(i, j)$ 作为起点,如果调用 $dfs(i, j, 0)$ 返回 true,就说明单词存在,否则说明单词不存在,返回 false

时间复杂度 $O(m \times n \times 3^k)$,空间复杂度 $O(\min(m \times n, k))$。其中 $m$ 和 $n$ 分别是网格的行数和列数;而 $k$ 是字符串 $word$ 的长度。

class Solution:
  def exist(self, board: List[List[str]], word: str) -> bool:
    def dfs(i: int, j: int, k: int) -> bool:
      if k == len(word) - 1:
        return board[i][j] == word[k]
      if board[i][j] != word[k]:
        return False
      c = board[i][j]
      board[i][j] = "0"
      for a, b in pairwise((-1, 0, 1, 0, -1)):
        x, y = i + a, j + b
        ok = 0 <= x < m and 0 <= y < n and board[x][y] != "0"
        if ok and dfs(x, y, k + 1):
          return True
      board[i][j] = c
      return False

    m, n = len(board), len(board[0])
    return any(dfs(i, j, 0) for i in range(m) for j in range(n))
class Solution {
  private int m;
  private int n;
  private String word;
  private char[][] board;

  public boolean exist(char[][] board, String word) {
    m = board.length;
    n = board[0].length;
    this.word = word;
    this.board = board;
    for (int i = 0; i < m; ++i) {
      for (int j = 0; j < n; ++j) {
        if (dfs(i, j, 0)) {
          return true;
        }
      }
    }
    return false;
  }

  private boolean dfs(int i, int j, int k) {
    if (k == word.length() - 1) {
      return board[i][j] == word.charAt(k);
    }
    if (board[i][j] != word.charAt(k)) {
      return false;
    }
    char c = board[i][j];
    board[i][j] = '0';
    int[] dirs = {-1, 0, 1, 0, -1};
    for (int u = 0; u < 4; ++u) {
      int x = i + dirs[u], y = j + dirs[u + 1];
      if (x >= 0 && x < m && y >= 0 && y < n && board[x][y] != '0' && dfs(x, y, k + 1)) {
        return true;
      }
    }
    board[i][j] = c;
    return false;
  }
}
class Solution {
public:
  bool exist(vector<vector<char>>& board, string word) {
    int m = board.size(), n = board[0].size();
    int dirs[5] = {-1, 0, 1, 0, -1};
    function<bool(int, int, int)> dfs = [&](int i, int j, int k) -> bool {
      if (k == word.size() - 1) {
        return board[i][j] == word[k];
      }
      if (board[i][j] != word[k]) {
        return false;
      }
      char c = board[i][j];
      board[i][j] = '0';
      for (int u = 0; u < 4; ++u) {
        int x = i + dirs[u], y = j + dirs[u + 1];
        if (x >= 0 && x < m && y >= 0 && y < n && board[x][y] != '0' && dfs(x, y, k + 1)) {
          return true;
        }
      }
      board[i][j] = c;
      return false;
    };
    for (int i = 0; i < m; ++i) {
      for (int j = 0; j < n; ++j) {
        if (dfs(i, j, 0)) {
          return true;
        }
      }
    }
    return false;
  }
};
func exist(board [][]byte, word string) bool {
  m, n := len(board), len(board[0])
  var dfs func(int, int, int) bool
  dfs = func(i, j, k int) bool {
    if k == len(word)-1 {
      return board[i][j] == word[k]
    }
    if board[i][j] != word[k] {
      return false
    }
    dirs := [5]int{-1, 0, 1, 0, -1}
    c := board[i][j]
    board[i][j] = '0'
    for u := 0; u < 4; u++ {
      x, y := i+dirs[u], j+dirs[u+1]
      if x >= 0 && x < m && y >= 0 && y < n && board[x][y] != '0' && dfs(x, y, k+1) {
        return true
      }
    }
    board[i][j] = c
    return false
  }
  for i := 0; i < m; i++ {
    for j := 0; j < n; j++ {
      if dfs(i, j, 0) {
        return true
      }
    }
  }
  return false
}
function exist(board: string[][], word: string): boolean {
  const [m, n] = [board.length, board[0].length];
  const dirs = [-1, 0, 1, 0, -1];
  const dfs = (i: number, j: number, k: number): boolean => {
    if (k === word.length - 1) {
      return board[i][j] === word[k];
    }
    if (board[i][j] !== word[k]) {
      return false;
    }
    const c = board[i][j];
    board[i][j] = '0';
    for (let u = 0; u < 4; ++u) {
      const [x, y] = [i + dirs[u], j + dirs[u + 1]];
      const ok = x >= 0 && x < m && y >= 0 && y < n;
      if (ok && board[x][y] !== '0' && dfs(x, y, k + 1)) {
        return true;
      }
    }
    board[i][j] = c;
    return false;
  };
  for (let i = 0; i < m; ++i) {
    for (let j = 0; j < n; ++j) {
      if (dfs(i, j, 0)) {
        return true;
      }
    }
  }
  return false;
}
impl Solution {
  fn dfs(
    i: usize,
    j: usize,
    c: usize,
    word: &[u8],
    board: &Vec<Vec<char>>,
    vis: &mut Vec<Vec<bool>>
  ) -> bool {
    if (board[i][j] as u8) != word[c] {
      return false;
    }
    if c == word.len() - 1 {
      return true;
    }
    vis[i][j] = true;
    let dirs = [
      [-1, 0],
      [0, -1],
      [1, 0],
      [0, 1],
    ];
    for [x, y] in dirs.into_iter() {
      let i = x + (i as i32);
      let j = y + (j as i32);
      if i < 0 || i == (board.len() as i32) || j < 0 || j == (board[0].len() as i32) {
        continue;
      }
      let (i, j) = (i as usize, j as usize);
      if !vis[i][j] && Self::dfs(i, j, c + 1, word, board, vis) {
        return true;
      }
    }
    vis[i][j] = false;
    false
  }

  pub fn exist(board: Vec<Vec<char>>, word: String) -> bool {
    let m = board.len();
    let n = board[0].len();
    let word = word.as_bytes();
    let mut vis = vec![vec![false; n]; m];
    for i in 0..m {
      for j in 0..n {
        if Self::dfs(i, j, 0, word, &board, &mut vis) {
          return true;
        }
      }
    }
    false
  }
}
public class Solution {
  private int m;
  private int n;
  private char[][] board;
  private string word;

  public bool Exist(char[][] board, string word) {
    m = board.Length;
    n = board[0].Length;
    this.board = board;
    this.word = word;
    for (int i = 0; i < m; ++i) {
      for (int j = 0; j < n; ++j) {
        if (dfs(i, j, 0)) {
          return true;
        }
      }
    }
    return false;
  }

  private bool dfs(int i, int j, int k) {
    if (k == word.Length - 1) {
      return board[i][j] == word[k];
    }
    if (board[i][j] != word[k]) {
      return false;
    }
    char c = board[i][j];
    board[i][j] = '0';
    int[] dirs = { -1, 0, 1, 0, -1 };
    for (int u = 0; u < 4; ++u) {
      int x = i + dirs[u];
      int y = j + dirs[u + 1];
      if (x >= 0 && x < m && y >= 0 && y < n && board[x][y] != '0' && dfs(x, y, k + 1)) {
        return true;
      }
    }
    board[i][j] = c;
    return false;
  }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文