Algorithms first

单词搜索 II · 交互式算法学习

在字符网格中找出词表里所有可由相邻格组成的单词。

#212 · 字典树

单词搜索 II

Word Search II

测试用例board = [[o,a,a,n],[e,t,a,e],[i,h,k,r],[i,f,l,v]], words = [oath,pea,eat,rain]
矩阵3 个关键状态
步骤 1Trie 根只允许 o、p、e、r 起步。prefix prune
o0,0
a0,1
a0,2
n0,3
e1,0
t1,1
a1,2
e1,3
i2,0
h2,1
k2,2
r2,3
i3,0
f3,1
l3,2
v3,3
推荐

Trie 剪枝 + 一次网格 DFS

时间 O(mn·4^L)空间 O(词表字符数)

词表建 Trie,网格路径只沿仍可能形成单词的前缀继续。

1function findWords(b, words) {2  const root = {};3  for (const w of words) {4    let n = root;5    for (const c of w) n = n[c] ??= {};6    n.word = w7  }8  const out = [];9 10  function dfs(r, c, n) {11    const ch = b[r]?.[c],12      next = n[ch];13    if (!next) return;14    if (next.word) {15      out.push(next.word);16      delete next.word17    }18    b[r][c] = '#';19    for (const [dr, dc] of [20        [1, 0],21        [-1, 0],22        [0, 1],23        [0, -1]24      ]) dfs(r + dr, c + dc, next);25    b[r][c] = ch;26    if (!Object.keys(next).length) delete n[ch]27  }28  for (let r = 0; r < b.length; r++)29    for (let c = 0; c < b[0].length; c++) dfs(r, c, root);30  return out;31}
多语言参考

Java · C++ · Go

来源 · CC BY-SA 4.0 ↗

这是一组同题正确实现,独立于上方当前动画方法;不同语言可能采用另一种正确策略。

1class Trie {2    Trie[] children = new Trie[26];3    int ref = -1;4 5    public void insert(String w, int ref) {6        Trie node = this;7        for (int i = 0; i < w.length(); ++i) {8            int j = w.charAt(i) - 'a';9            if (node.children[j] == null) {10                node.children[j] = new Trie();11            }12            node = node.children[j];13        }14        node.ref = ref;15    }16}17 18class Solution {19    private char[][] board;20    private String[] words;21    private List<String> ans = new ArrayList<>();22 23    public List<String> findWords(char[][] board, String[] words) {24        this.board = board;25        this.words = words;26        Trie tree = new Trie();27        for (int i = 0; i < words.length; ++i) {28            tree.insert(words[i], i);29        }30        int m = board.length, n = board[0].length;31        for (int i = 0; i < m; ++i) {32            for (int j = 0; j < n; ++j) {33                dfs(tree, i, j);34            }35        }36        return ans;37    }38 39    private void dfs(Trie node, int i, int j) {40        int idx = board[i][j] - 'a';41        if (node.children[idx] == null) {42            return;43        }44        node = node.children[idx];45        if (node.ref != -1) {46            ans.add(words[node.ref]);47            node.ref = -1;48        }49        char c = board[i][j];50        board[i][j] = '#';51        int[] dirs = {-1, 0, 1, 0, -1};52        for (int k = 0; k < 4; ++k) {53            int x = i + dirs[k], y = j + dirs[k + 1];54            if (x >= 0 && x < board.length && y >= 0 && y < board[0].length && board[x][y] != '#') {55                dfs(node, x, y);56            }57        }58        board[i][j] = c;59    }60}
交互式算法学习

从执行步骤真正理解 LeetCode 经典 150

本站整理 150 道高频算法面试题和 302 种解法。动画方法同步展示 JavaScript 与 Python;每题另提供 Java、C++ 与 Go 同题参考实现。

多形态可视化数组、矩阵、DP 表、递归树、树图、链表、栈队列堆、区间和状态机按解法选择。
动画与代码同步当前状态、步骤说明、变量和代码高亮保持一一对应,可逐步播放和回退。
适合面试复习每种方案都给出思路、时间复杂度、空间复杂度、测试用例和 LeetCode 中文原题入口。
AlgoViz Lab

单词搜索 II · 解法对比

在字符网格中找出词表里所有可由相邻格组成的单词。

测试用例
board = [[o,a,a,n],[e,t,a,e],[i,h,k,r],[i,f,l,v]], words = [oath,pea,eat,rain]
题目分类
字典树
解法对比
2
方案 1

每个单词单独回溯

对词表每个单词从每个格子启动 DFS。

时间
O(W·mn·4^L)
空间
O(L)
方案 2

Trie 剪枝 + 一次网格 DFS

词表建 Trie,网格路径只沿仍可能形成单词的前缀继续。

时间
O(mn·4^L)
空间
O(词表字符数)