题目描述
给定一个 m x n 二维字符网格 board 和一个字符串单词 word。如果 word 存在于网格中,返回 true;否则,返回 false。
单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中”相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。
进阶:你可以使用搜索剪枝的技术来优化解决方案,使其在 board 更大的情况下可以更快解决问题?
示例 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
思路&js代码
1、回溯
var exist = function(board, word) {
const m = board.length, n = board[0].length;
function dfs(i, j, k) {
if (board[i][j] !== word[k]) {
return false; // 匹配失败
}
if (k + 1 === word.length) {
return true; // 匹配成功!
}
board[i][j] = 0; // 标记访问过
for (const [x, y] of [[i, j - 1], [i, j + 1], [i - 1, j], [i + 1, j]]) { // 相邻格子
if (0 <= x && x < m && 0 <= y && y < n && dfs(x, y, k + 1)) {
return true; // 搜到了!
}
}
board[i][j] = word[k]; // 恢复现场
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; // 没搜到
};2、优化
var exist = function(board, word) {
const cnt = new Map();
for (const row of board) {
for (const c of row) {
cnt.set(c, (cnt.get(c) ?? 0) + 1);
}
}
// 优化一
const wordCnt = new Map();
for (const c of word) {
wordCnt.set(c, (wordCnt.get(c) ?? 0) + 1);
if (wordCnt.get(c) > (cnt.get(c) ?? 0)) {
return false;
}
}
// 优化二
if ((cnt.get(word[word.length - 1]) ?? 0) < (cnt.get(word[0]) ?? 0)) {
word = word.split('').reverse();
}
const m = board.length, n = board[0].length;
function dfs(i, j, k) {
if (board[i][j] !== word[k]) {
return false; // 匹配失败
}
if (k + 1 === word.length) {
return true; // 匹配成功!
}
board[i][j] = 0; // 标记访问过
for (const [x, y] of [[i, j - 1], [i, j + 1], [i - 1, j], [i + 1, j]]) { // 相邻格子
if (0 <= x && x < m && 0 <= y && y < n && dfs(x, y, k + 1)) {
return true; // 搜到了!
}
}
board[i][j] = word[k]; // 恢复现场
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; // 没搜到
};