|
| 1 | +from collections import Counter |
| 2 | +from typing import List |
| 3 | + |
1 | 4 | class Solution: |
2 | 5 | def exist(self, board: List[List[str]], word: str) -> bool: |
3 | | - for i in range(len(board)): |
4 | | - for j in range(len(board[0])): |
5 | | - if self.dfs(board, word, i, j): |
6 | | - return True |
| 6 | + row_len, col_len = len(board), len(board[0]) |
7 | 7 |
|
8 | | - return False |
| 8 | + board_freq = Counter(ch for row in board for ch in row) |
9 | 9 |
|
10 | | - def dfs(self, board: List[List[str]], word: str, i: int, j: int): |
11 | | - if board[i][j] != word[0] or board[i][j] == "-1": |
12 | | - return False |
13 | | - if len(word) == 1: |
14 | | - return True |
| 10 | + if board_freq.get(word[0], 0) > board_freq.get(word[-1], 0): |
| 11 | + word = word[::-1] |
| 12 | + |
| 13 | + DIRECTIONS = ((-1, 0), (1, 0), (0, -1), (0, 1)) |
| 14 | + MARKER = "" |
| 15 | + |
| 16 | + def in_bounds(r: int, c: int) -> bool: |
| 17 | + return 0 <= r < row_len and 0 <= c < col_len |
15 | 18 |
|
16 | | - temp_cell = board[i][j] |
17 | | - board[i][j] = "-1" |
18 | | - word = word[1:] |
19 | | - if i >= 1 and self.dfs(board, word, i - 1, j): |
20 | | - return True |
| 19 | + def backtrack(r: int, c: int, idx: int) -> bool: |
| 20 | + for ch, need in Counter(word[idx:]).items(): |
| 21 | + if board_freq.get(ch, 0) < need: |
| 22 | + return False |
21 | 23 |
|
22 | | - if j >= 1 and self.dfs(board, word, i, j - 1): |
23 | | - return True |
| 24 | + if idx == len(word) - 1: |
| 25 | + return True |
24 | 26 |
|
25 | | - if i < len(board) - 1 and self.dfs(board, word, i + 1, j): |
26 | | - return True |
| 27 | + saved_char = board[r][c] |
| 28 | + board[r][c] = MARKER |
| 29 | + board_freq[saved_char] -= 1 |
27 | 30 |
|
28 | | - if j < len(board[0]) - 1 and self.dfs(board, word, i, j + 1): |
29 | | - return True |
| 31 | + for dr, dc in DIRECTIONS: |
| 32 | + nr, nc = r + dr, c + dc |
| 33 | + next_ch = word[idx + 1] |
| 34 | + |
| 35 | + if (in_bounds(nr, nc) |
| 36 | + and board[nr][nc] != MARKER |
| 37 | + and board[nr][nc] == next_ch |
| 38 | + and board_freq[next_ch] > 0 |
| 39 | + and backtrack(nr, nc, idx + 1)): |
| 40 | + return True |
| 41 | + |
| 42 | + board[r][c] = saved_char |
| 43 | + board_freq[saved_char] += 1 |
| 44 | + return False |
| 45 | + |
| 46 | + for r in range(row_len): |
| 47 | + for c in range(col_len): |
| 48 | + if board[r][c] == word[0] and backtrack(r, c, 0): |
| 49 | + return True |
30 | 50 |
|
31 | | - board[i][j] = temp_cell |
32 | 51 | return False |
0 commit comments