Return true if word can be traced on the grid through horizontally or vertically adjacent cells, using each cell at most once.
Two cheap checks first: if the board lacks enough of some letter, fail immediately. If the word's last letter is rarer than its first, search for the reversed word, which cuts off more branches early.
1function exist(board: string[][], word: string): boolean {2const total = new Map<string, number>(), need = new Map<string, number>();3for (const row of board) for (const ch of row) total.set(ch, (total.get(ch) ?? 0) + 1);4for (const ch of word) {5need.set(ch, (need.get(ch) ?? 0) + 1);6if (need.get(ch)! > (total.get(ch) ?? 0)) return false;7}8const freq = (ch: string) => total.get(ch) ?? 0;9if (freq(word[0]) > freq(word[word.length - 1])) word = [...word].reverse().join("");10// ...then the same backtracking search as before11const m = board.length, n = board[0].length;12function dfs(r: number, c: number, k: number): boolean {13if (k === word.length) return true;14if (r < 0 || c < 0 || r >= m || c >= n || board[r][c] !== word[k]) return false;15const ch = board[r][c];16board[r][c] = "#";17const ok = dfs(r + 1, c, k + 1) || dfs(r - 1, c, k + 1) || dfs(r, c + 1, k + 1) || dfs(r, c - 1, k + 1);18board[r][c] = ch;19return ok;20}21for (let r = 0; r < m; r++)22for (let c = 0; c < n; c++) if (dfs(r, c, 0)) return true;23return false;24}
Count the letters on the board.
Space: play/pause · ←/→: step