题目LeetCode 79
给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中,返回 true ;否则,返回 false 。
单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中"相邻"单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。
示例:

输入: board = [['A','B','C','E'],['S','F','C','S'],['A','D','E','E']], word = "ABCCED"
**输出:**true
Python解法
代码示例(回溯+DFS)
python
from typing import List
class Solution:
def exist(self, board: List[List[str]], word: str) -> bool:
m = len(board)
n = len(board[0])
dirs = [(-1, 0), (1, 0), (0, -1), (0, 1)]
def dfs(i , j, k):
if board[i][j] != word[k]:
return False
if k == len(word) - 1:
return True
temp = board[i][j]
board[i][j] = '#'
for dx, dy in dirs:
x = i + dx
y = j + dy
if 0<=x<m and 0<=y<n:
if dfs(x, y, k + 1):
return True
board[i][j] = temp
return False
for i in range(m):
for j in range(n):
if dfs(i, j, 0):
return True
return False
解释
1, 首先测长度,设置移动方向
python
m = len(board)
n = len(board[0])
# 上下左右
dirs = [(-1,0), (1,0), (0,-1), (0,1)]
2, 然后是主要函数,首先判断不匹配与匹配成功
python
# 1. 字符不匹配,直接返回
if board[i][j] != word[k]:
return False
# 2. 已经匹配到最后一个字母,成功
if k == len(word) - 1:
return True
3, 标记走过的,避免回头
举个例子
你现在走的路径是:A → B → C
你走到 B 的时候,**必须把 B 改成 #**不然会发生这种事:
A ← B → C
python
temp = board[i][j] # 先把原来的字母存起来
board[i][j] = '#' # 把当前格子改成 # ------ 这就是【标记】
4,每个方向都试一试,不越界才往下进行,如果成功直接返回True
python
# 四个方向走一走
for dx, dy in dirs:
x = i + dx
y = j + dy
if 0 <= x < m and 0 <= y < n:
if dfs(x, y, k + 1):
return True # 找到就直接返回
5, 恢复原样
为什么要恢复?因为你这条路走不通,不代表别的路不能用这个格子!
看例子:你现在走:A → B → X(走不通)
你退回来的时候,必须把 B 恢复成 B不然别人想走:C → B → D就走不了了,因为 B 被你改成 # 废掉了。
python
board[i][j] = tmp # 把 # 改回原来的字母 ------ 这就是【恢复】
6,将从格子里的各个部分都当一次起点
python
# 每个格子都当起点试一次
for i in range(m):
for j in range(n):
if dfs(i, j, 0):
return True
过程演示

Java解法(回溯+DFS)
java
import java.util.*;
class Solution {
public boolean exist(char[][] board, String word) {
// 行列 定义在 public 里面
int m = board.length;
int n = board[0].length;
// 四个方向 定义在 public 里面
int[][] dirs = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
// 遍历每个起点
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (dfs(board, word, i, j, 0, m, n, dirs)) {
return true;
}
}
}
return false;
}
// DFS 递归函数
private boolean dfs(char[][] board, String word, int i, int j, int k,
int m, int n, int[][] dirs) {
// 字符不匹配直接返回
if (board[i][j] != word.charAt(k)) {
return false;
}
// 匹配到最后一位,成功
if (k == word.length() - 1) {
return true;
}
// 标记已访问
char temp = board[i][j];
board[i][j] = '#';
// 四个方向搜索
for (int[] dir : dirs) {
int x = i + dir[0];
int y = j + dir[1];
if (x >= 0 && x < m && y >= 0 && y < n) {
if (dfs(board, word, x, y, k + 1, m, n, dirs)) {
return true;
}
}
}
// 回溯恢复
board[i][j] = temp;
return false;
}
}
C++解法(回溯+DFS)
cpp
#include <vector>
#include <string>
using namespace std;
class Solution {
public:
bool exist(vector<vector<char>>& board, string word) {
int m = board.size(); // C++ 用 .size()
int n = board[0].size();
// 四个方向:上下左右
vector<vector<int>> dirs = {{-1,0}, {1,0}, {0,-1}, {0,1}};
// 遍历每个起点
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (dfs(board, word, i, j, 0, m, n, dirs)) {
return true;
}
}
}
return false;
}
private:
bool dfs(vector<vector<char>>& board, string word, int i, int j, int k,
int m, int n, vector<vector<int>>& dirs) {
// 字符不匹配直接返回
if (board[i][j] != word[k]) { // C++ string 可以直接用 []
return false;
}
// 匹配到最后一位,成功
if (k == word.size() - 1) {
return true;
}
// 标记已访问
char temp = board[i][j];
board[i][j] = '#';
// 四个方向搜索
for (auto& dir : dirs) { // C++ 增强for循环
int x = i + dir[0];
int y = j + dir[1];
if (x >= 0 && x < m && y >= 0 && y < n) {
if (dfs(board, word, x, y, k+1, m, n, dirs)) {
return true;
}
}
}
// 回溯恢复
board[i][j] = temp;
return false;
}
};