题目: 单词搜索
来自智得网
方法一:回溯法
回溯法是解决单词搜索问题的常见方法。它通过深度优先搜索(DFS)的方式遍历矩阵中的每个位置,逐步构建单词,并进行回溯。具体步骤如下:
- 遍历矩阵中的每个位置,作为单词的起点。
- 对于每个起点位置,使用深度优先搜索进行回溯,判断当前位置是否匹配单词的第一个字母。
- 若匹配,则继续向上、下、左、右四个方向进行搜索,递归调用回溯函数。
- 在搜索过程中,判断当前位置是否越界、是否已经访问过、是否匹配当前单词字符等条件。
- 若遍历到单词的最后一个字符,且所有字符都匹配成功,则找到了目标单词,返回true。
- 若所有起点位置都搜索完毕,仍未找到目标单词,则返回false。
class Solution {
public:
bool exist(vector<vector<char>>& board, string word) {
if (board.empty() || board[0].empty()) return false;
int m = board.size();
int n = board[0].size();
vector<vector<bool>> visited(m, vector<bool>(n, false));
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (dfs(board, word, visited, i, j, 0)) {
return true;
}
}
}
return false;
}
private:
bool dfs(vector<vector<char>>& board, string& word, vector<vector<bool>>& visited, int i, int j, int k) {
if (k == word.length()) return true;
if (i < 0 || i >= board.size() || j < 0 || j >= board[0].size() || visited[i][j] || board[i][j] != word[k]) {
return false;
}
visited[i][j] = true;
bool res = dfs(board, word, visited, i - 1, j, k + 1) ||
dfs(board, word, visited, i + 1, j, k + 1) ||
dfs(board, word, visited, i, j - 1, k + 1) ||
dfs(board, word, visited, i, j + 1, k + 1);
visited[i][j] = false;
return res;
}
};
class Solution {
public boolean exist(char[][] board, String word) {
if (board == null || board.length == 0 || board[0].length == 0) return false;
int m = board.length;
int n = board[0].length;
boolean[][] visited = new boolean[m][n];
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (dfs(board, word, visited, i, j, 0)) {
return true;
}
}
}
return false;
}
private boolean dfs(char[][] board, String word, boolean[][] visited, int i, int j, int k) {
if (k == word.length()) return true;
if (i < 0 || i >= board.length || j < 0 || j >= board[0].length || visited[i][j] || board[i][j] != word.charAt(k)) {
return false;
}
visited[i][j] = true;
boolean res = dfs(board, word, visited, i - 1, j, k + 1) ||
dfs(board, word, visited, i + 1, j, k + 1) ||
dfs(board, word, visited, i, j - 1, k + 1) ||
dfs(board, word, visited, i, j + 1, k + 1);
visited[i][j] = false;
return res;
}
}
func exist(board [][]byte, word string) bool {
if len(board) == 0 || len(board[0]) == 0 {
return false
}
m, n := len(board), len(board[0])
visited := make([][]bool, m)
for i := 0; i < m; i++ {
visited[i] = make([]bool, n)
}
for i := 0; i < m; i++ {
for j := 0; j < n; j++ {
if dfs(board, word, visited, i, j, 0) {
return true
}
}
}
return false
}
func dfs(board [][]byte, word string, visited [][]bool, i, j, k int) bool {
if k == len(word) {
return true
}
if i < 0 || i >= len(board) || j < 0 || j >= len(board[0]) || visited[i][j] || board[i][j] != word[k] {
return false
}
visited[i][j] = true
res := dfs(board, word, visited, i-1, j, k+1) ||
dfs(board, word, visited, i+1, j, k+1) ||
dfs(board, word, visited, i, j-1, k+1) ||
dfs(board, word, visited, i, j+1, k+1)
visited[i][j] = false
return res
}
class Solution:
def exist(self, board: List[List[str]], word: str) -> bool:
if not board or not board[0]:
return False
m, n = len(board), len(board[0])
visited = [[False] * n for _ in range(m)]
for i in range(m):
for j in range(n):
if self.dfs(board, word, visited, i, j, 0):
return True
return False
def dfs(self, board, word, visited, i, j, k):
if k == len(word):
return True
if i < 0 or i >= len(board) or j < 0 or j >= len(board[0]) or visited[i][j] or board[i][j] != word[k]:
return False
visited[i][j] = True
res = self.dfs(board, word, visited, i - 1, j, k + 1) or \
self.dfs(board, word, visited, i + 1, j, k + 1) or \
self.dfs(board, word, visited, i, j - 1, k + 1) or \
self.dfs(board, word, visited, i, j + 1, k + 1)
visited[i][j] = False
return res
var exist = function(board, word) {
if (!board || !board.length || !board[0].length) return false;
const m = board.length;
const n = board[0].length;
const visited = Array.from(Array(m), () => Array(n).fill(false));
for (let i = 0; i < m; i++) {
for (let j = 0; j < n; j++) {
if (dfs(board, word, visited, i, j, 0)) {
return true;
}
}
}
return false;
};
const dfs = (board, word, visited, i, j, k) => {
if (k === word.length) return true;
if (i < 0 || i >= board.length || j < 0 || j >= board[0].length || visited[i][j] || board[i][j] !== word.charAt(k)) {
return false;
}
visited[i][j] = true;
const res = dfs(board, word, visited, i - 1, j, k + 1) ||
dfs(board, word, visited, i + 1, j, k + 1) ||
dfs(board, word, visited, i, j - 1, k + 1) ||
dfs(board, word, visited, i, j + 1, k + 1);
visited[i][j] = false;
return res;
};
方法二:Trie树(前缀树)
Trie树是一种专门用于解决字符串匹配问题的数据结构。它通过构建多叉树的形式,将字符串按字符逐层存储,从而快速定位和搜索目标字符串。具体步骤如下:
- 构建Trie树:将所有目标单词插入到Trie树中,每个节点表示一个字符。
- 遍历矩阵中的每个位置,作为单词的起点。
- 对于每个起点位置,判断当前位置的字符是否存在于Trie树的根节点中。
- 若存在,则从当前位置开始,向上、下、左、右四个方向进行深度优先搜索,同时在Trie树中移动到下一个字符节点。
- 在搜索过程中,判断当前位置是否越界、是否已经访问过、是否匹配当前Trie树节点等条件。
- 若遍历到单词的最后一个字符,且所有字符都匹配成功,则找到了目标单词,返回true。
- 若所有起点位置都搜索完毕,仍未找到目标单词,则返回false。
class Solution {
public:
bool exist(vector<vector<char>>& board, string word) {
if (board.empty() || board[0].empty()) {
return false;
}
int m = board.size();
int n = board[0].size();
vector<vector<bool>> visited(m, vector<bool>(n, false));
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (dfs(board, word, visited, i, j, 0)) {
return true;
}
}
}
return false;
}
bool dfs(vector<vector<char>>& board, string& word, vector<vector<bool>>& visited, int i, int j, int k) {
if (k == word.length()) {
return true;
}
if (i < 0 || i >= board.size() || j < 0 || j >= board[0].size() || visited[i][j] || board[i][j] != word[k]) {
return false;
}
visited[i][j] = true;
bool res = dfs(board, word, visited, i - 1, j, k + 1) ||
dfs(board, word, visited, i + 1, j, k + 1) ||
dfs(board, word, visited, i, j - 1, k + 1) ||
dfs(board, word, visited, i, j + 1, k + 1);
visited[i][j] = false;
return res;
}
};
class Solution {
public boolean exist(char[][] board, String word) {
if (board == null || board.length == 0 || board[0].length == 0) {
return false;
}
int m = board.length;
int n = board[0].length;
boolean[][] visited = new boolean[m][n];
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (dfs(board, word, visited, i, j, 0)) {
return true;
}
}
}
return false;
}
private boolean dfs(char[][] board, String word, boolean[][] visited, int i, int j, int k) {
if (k == word.length()) {
return true;
}
if (i < 0 || i >= board.length || j < 0 || j >= board[0].length || visited[i][j] || board[i][j] != word.charAt(k)) {
return false;
}
visited[i][j] = true;
boolean res = dfs(board, word, visited, i - 1, j, k + 1) ||
dfs(board, word, visited, i + 1, j, k + 1) ||
dfs(board, word, visited, i, j - 1, k + 1) ||
dfs(board, word, visited, i, j + 1, k + 1);
visited[i][j] = false;
return res;
}
}
func exist(board [][]byte, word string) bool {
if len(board) == 0 || len(board[0]) == 0 {
return false
}
m := len(board)
n := len(board[0])
visited := make([][]bool, m)
for i := 0; i < m; i++ {
visited[i] = make([]bool, n)
}
for i := 0; i < m; i++ {
for j := 0; j < n; j++ {
if dfs(board, word, visited, i, j, 0) {
return true
}
}
}
return false
}
func dfs(board [][]byte, word string, visited [][]bool, i, j, k int) bool {
if k == len(word) {
return true
}
if i < 0 || i >= len(board) || j < 0 || j >= len(board[0]) || visited[i][j] || board[i][j] != word[k] {
return false
}
visited[i][j] = true
res := dfs(board, word, visited, i-1, j, k+1) ||
dfs(board, word, visited, i+1, j, k+1) ||
dfs(board, word, visited, i, j-1, k+1) ||
dfs(board, word, visited, i, j+1, k+1)
visited[i][j] = false
return res
}
class Solution:
def exist(self, board: List[List[str]], word: str) -> bool:
if not board or not board[0]:
return False
m, n = len(board), len(board[0])
visited = [[False] * n for _ in range(m)]
for i in range(m):
for j in range(n):
if self.dfs(board, word, visited, i, j, 0):
return True
return False
def dfs(self, board, word, visited, i, j, k):
if k == len(word):
return True
if i < 0 or i >= len(board) or j < 0 or j >= len(board[0]) or visited[i][j] or board[i][j] != word[k]:
return False
visited[i][j] = True
res = self.dfs(board, word, visited, i - 1, j, k + 1) or \
self.dfs(board, word, visited, i + 1, j, k + 1) or \
self.dfs(board, word, visited, i, j - 1, k + 1) or \
self.dfs(board, word, visited, i, j + 1, k + 1)
visited[i][j] = False
return res
var exist = function(board, word) {
if (!board || !board.length || !board[0].length) {
return false;
}
let m = board.length;
let n = board[0].length;
let visited = new Array(m).fill(false).map(() => new Array(n).fill(false));
for (let i = 0; i < m; i++) {
for (let j = 0; j < n; j++) {
if (dfs(board, word, visited, i, j, 0)) {
return true;
}
}
}
return false;
};
var dfs = function(board, word, visited, i, j, k) {
if (k === word.length) {
return true;
}
if (i < 0 || i >= board.length || j < 0 || j >= board[0].length || visited[i][j] || board[i][j] !== word.charAt(k)) {
return false;
}
visited[i][j] = true;
let res = dfs(board, word, visited, i - 1, j, k + 1) ||
dfs(board, word, visited, i + 1, j, k + 1) ||
dfs(board, word, visited, i, j - 1, k + 1) ||
dfs(board, word, visited, i, j + 1, k + 1);
visited[i][j] = false;
return res;
};
方法三:DFS + 剪枝
在回溯法的基础上,通过剪枝操作来提前终止无效搜索,提高效率。具体步骤如下:
- 遍历矩阵中的每个位置,作为单词的起点。
- 对于每个起点位置,使用深度优先搜索进行回溯,判断当前位置是否匹配单词的第一个字母。
- 若匹配,则继续向上、下、左、右四个方向进行搜索,递归调用回溯函数。
- 在搜索过程中,判断当前位置是否越界、是否已经访问过、是否匹配当前单词字符等条件。
- 在每次递归调用时,判断剩余单词是否能够在当前位置的周围找到,若不能找到,则进行剪枝操作,提前结束搜索。
- 在搜索过程中,若已经找到目标单词,则直接返回true。
- 若所有起点位置都搜索完毕,仍未找到目标单词,则返回false。
class Solution {
public:
bool exist(vector<vector<char>>& board, string word) {
if (board.empty() || board[0].empty()) {
return false;
}
int m = board.size();
int n = board[0].size();
vector<vector<bool>> visited(m, vector<bool>(n, false));
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (dfs(board, word, visited, i, j, 0)) {
return true;
}
}
}
return false;
}
bool dfs(vector<vector<char>>& board, string word, vector<vector<bool>>& visited, int i, int j, int k) {
if (k == word.size()) {
return true;
}
if (i < 0 || i >= board.size() || j < 0 || j >= board[0].size() || visited[i][j] || board[i][j] != word[k]) {
return false;
}
visited[i][j] = true;
bool res = dfs(board, word, visited, i - 1, j, k + 1) ||
dfs(board, word, visited, i + 1, j, k + 1) ||
dfs(board, word, visited, i, j - 1, k + 1) ||
dfs(board, word, visited, i, j + 1, k + 1);
visited[i][j] = false;
return res;
}
};
class Solution {
public boolean exist(char[][] board, String word) {
if (board == null || board.length == 0 || board[0].length == 0) {
return false;
}
int m = board.length;
int n = board[0].length;
boolean[][] visited = new boolean[m][n];
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (dfs(board, word, visited, i, j, 0)) {
return true;
}
}
}
return false;
}
private boolean dfs(char[][] board, String word, boolean[][] visited, int i, int j, int k) {
if (k == word.length()) {
return true;
}
if (i < 0 || i >= board.length || j < 0 || j >= board[0].length || visited[i][j] || board[i][j] != word.charAt(k)) {
return false;
}
visited[i][j] = true;
boolean res = dfs(board, word, visited, i - 1, j, k + 1) ||
dfs(board, word, visited, i + 1, j, k + 1) ||
dfs(board, word, visited, i, j - 1, k + 1) ||
dfs(board, word, visited, i, j + 1, k + 1);
visited[i][j] = false;
return res;
}
}
func exist(board [][]byte, word string) bool {
if len(board) == 0 || len(board[0]) == 0 {
return false
}
m, n := len(board), len(board[0])
visited := make([][]bool, m)
for i := 0; i < m; i++ {
visited[i] = make([]bool, n)
}
for i := 0; i < m; i++ {
for j := 0; j < n; j++ {
if dfs(board, word, visited, i, j, 0) {
return true
}
}
}
return false
}
func dfs(board [][]byte, word string, visited [][]bool, i, j, k int) bool {
if k == len(word) {
return true
}
if i < 0 || i >= len(board) || j < 0 || j >= len(board[0]) || visited[i][j] || board[i][j] != word[k] {
return false
}
visited[i][j] = true
res := dfs(board, word, visited, i-1, j, k+1) ||
dfs(board, word, visited, i+1, j, k+1) ||
dfs(board, word, visited, i, j-1, k+1) ||
dfs(board, word, visited, i, j+1, k+1)
visited[i][j] = false
return res
}
class Solution:
def exist(self, board: List[List[str]], word: str) -> bool:
if not board or not board[0]:
return False
m, n = len(board), len(board[0])
visited = [[False] * n for _ in range(m)]
for i in range(m):
for j in range(n):
if self.dfs(board, word, visited, i, j, 0):
return True
return False
def dfs(self, board, word, visited, i, j, k):
if k == len(word):
return True
if i < 0 or i >= len(board) or j < 0 or j >= len(board[0]) or visited[i][j] or board[i][j] != word[k]:
return False
visited[i][j] = True
res = self.dfs(board, word, visited, i-1, j, k+1) \
or self.dfs(board, word, visited, i+1, j, k+1) \
or self.dfs(board, word, visited, i, j-1, k+1) \
or self.dfs(board, word, visited, i, j+1, k+1)
visited[i][j] = False
return res
var exist = function(board, word) {
if (!board || !board.length || !board[0].length) {
return false;
}
const m = board.length;
const n = board[0].length;
const visited = Array.from(Array(m), () => new Array(n).fill(false));
for (let i = 0; i < m; i++) {
for (let j = 0; j < n; j++) {
if (dfs(board, word, visited, i, j, 0)) {
return true;
}
}
}
return false;
};
const dfs = function(board, word, visited, i, j, k) {
if (k === word.length) {
return true;
}
if (i < 0 || i >= board.length || j < 0 || j >= board[0].length || visited[i][j] || board[i][j] !== word.charAt(k)) {
return false;
}
visited[i][j] = true;
const res = dfs(board, word, visited, i-1, j, k+1) ||
dfs(board, word, visited, i+1, j, k+1) ||
dfs(board, word, visited, i, j-1, k+1) ||
dfs(board, word, visited, i, j+1, k+1);
visited[i][j] = false;
return res;
};