- Remove all "## Java 解法" sections and Java code blocks - Replace "## Go 解法" with "## 解法" - Remove "### Go 代码要点" and "### Java 代码要点" sections - Keep all Go code sections intact - Maintain complete documentation structure and content - Update 22 markdown files in the LeetCode Hot 100 directory
133 lines
2.8 KiB
Markdown
133 lines
2.8 KiB
Markdown
# 单词搜索 (Word Search)
|
||
|
||
## 题目描述
|
||
|
||
给定一个 `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
|
||
```
|
||
|
||
## 解题思路
|
||
|
||
### 方法一:DFS + 回溯(推荐)
|
||
|
||
**核心思想:**对每个位置进行 DFS,搜索是否存在匹配的单词路径。
|
||
|
||
**算法步骤:**
|
||
1. 遍历网格的每个位置
|
||
2. 如果当前位置字符匹配单词首字符,开始 DFS
|
||
3. DFS 过程中:
|
||
- 标记当前已访问
|
||
- 向四个方向递归搜索
|
||
- 如果找到完整单词,返回 true
|
||
- 回溯时撤销访问标记
|
||
|
||
## 代码实现
|
||
|
||
### Go 实现
|
||
|
||
```go
|
||
package main
|
||
|
||
func exist(board [][]byte, word string) bool {
|
||
m, n := len(board), len(board[0])
|
||
visited := make([][]bool, m)
|
||
for i := range visited {
|
||
visited[i] = make([]bool, n)
|
||
}
|
||
|
||
var dfs func(i, j, k int) bool
|
||
dfs = func(i, j, k int) bool {
|
||
// 找到完整单词
|
||
if k == len(word) {
|
||
return true
|
||
}
|
||
|
||
// 边界检查或不匹配
|
||
if i < 0 || i >= m || j < 0 || j >= n ||
|
||
visited[i][j] || board[i][j] != word[k] {
|
||
return false
|
||
}
|
||
|
||
// 标记访问
|
||
visited[i][j] = true
|
||
|
||
// 向四个方向搜索
|
||
found := dfs(i+1, j, k+1) ||
|
||
dfs(i-1, j, k+1) ||
|
||
dfs(i, j+1, k+1) ||
|
||
dfs(i, j-1, k+1)
|
||
|
||
// 回溯:取消标记
|
||
visited[i][j] = false
|
||
|
||
return found
|
||
}
|
||
|
||
for i := 0; i < m; i++ {
|
||
for j := 0; j < n; j++ {
|
||
if board[i][j] == word[0] && dfs(i, j, 0) {
|
||
return true
|
||
}
|
||
}
|
||
}
|
||
|
||
return false
|
||
}
|
||
```
|
||
|
||
### Java 实现
|
||
|
||
|
||
## 复杂度分析
|
||
|
||
- **时间复杂度:** O(m × n × 4^L)
|
||
- m × n 是网格大小
|
||
- L 是单词长度
|
||
- 最坏情况每个位置都要搜索 4 个方向
|
||
|
||
- **空间复杂度:** O(L)
|
||
- 递归栈深度最大为 L
|
||
- visited 数组 O(m × n)
|
||
|
||
## P7 加分项
|
||
|
||
### 变形题目:单词搜索 II
|
||
|
||
**LeetCode 212:** 给定一个 m x n 二维字符网格 board 和一个单词列表 words,返回所有在二维网格和字典中出现的单词。
|
||
|
||
```go
|
||
func findWords(board [][]byte, words []string) []string {
|
||
// 构建 Trie 树
|
||
trie := buildTrie(words)
|
||
result := []string{}
|
||
|
||
for i := 0; i < len(board); i++ {
|
||
for j := 0; j < len(board[0]); j++ {
|
||
dfsBoard(board, i, j, trie, &result)
|
||
}
|
||
}
|
||
|
||
return result
|
||
}
|
||
```
|