Skip to content

Commit f511918

Browse files
committed
feat: solve DaleStudy#290 with python
1 parent c202261 commit f511918

File tree

1 file changed

+112
-0
lines changed

1 file changed

+112
-0
lines changed

word-search-ii/EGON.py

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
from typing import List
2+
from unittest import TestCase, main
3+
4+
5+
class Node:
6+
7+
def __init__(self, key, data=None):
8+
self.key = key
9+
self.data = data
10+
self.children = {}
11+
12+
13+
class Trie:
14+
15+
def __init__(self):
16+
self.root = Node(None)
17+
18+
def insert(self, word: str) -> None:
19+
curr_node = self.root
20+
for char in word:
21+
if char not in curr_node.children:
22+
curr_node.children[char] = Node(char)
23+
24+
curr_node = curr_node.children[char]
25+
26+
curr_node.data = word
27+
28+
29+
class Solution:
30+
def findWords(self, board: List[List[str]], words: List[str]) -> List[str]:
31+
return self.solve_trie_dfs(board, words)
32+
33+
"""
34+
* Constraints:
35+
1. m == board.length
36+
2. n == board[i].length
37+
3. 1 <= m, n <= 12
38+
4. board[i][j] is a lowercase English letter.
39+
5. 1 <= words.length <= 3 * 104
40+
6. 1 <= words[i].length <= 10
41+
7. words[i] consists of lowercase English letters.
42+
8. All the strings of words are unique.
43+
44+
Runtime: 6439 ms (Beats 26.38%)
45+
Time Complexity: O(R * C * (4 ^ max L))
46+
- word의 최대 길이를 max L, words의 길이를 K라 하면, trie에 words를 모두 insert하는데 O(max L * K), upper bound
47+
- board의 각 grid에서 조회하는데 O(R * C)
48+
- grid마다 dfs 호출하는데, dfs의 방향은 4곳이고, 호출 스택의 최대 깊이는 max L 이므로, * O(4 ^ max L)
49+
> O(max L * K) + O(R * C) * O(4 ^ max L) ~= O(R * C * (4 ^ max L))
50+
51+
Memory: 19.04 MB (Beats 20.79%)
52+
Space Complexity: O(max L * K)
53+
- trie의 공간 복잡도는 O(max L * K), upper bound
54+
- board의 각 grid에서 dfs를 호출하고, dfs 호출 스택의 최대 깊이는 max L 이므로 O(max L)
55+
- result의 최대 크기는 words의 길이와 같으므로 O(K), upper bound
56+
> O(max L * K) + O(max L) + O(K) ~= O(max L * K)
57+
"""
58+
def solve_trie_dfs(self, board: List[List[str]], words: List[str]) -> List[str]:
59+
MAX_R, MAX_C = len(board), len(board[0])
60+
DIRS = [(0, 1), (1, 0), (0, -1), (-1, 0)]
61+
62+
trie = Trie()
63+
for word in words:
64+
trie.insert(word)
65+
66+
def dfs(curr: Node, r: int, c: int, path: str):
67+
nonlocal result
68+
69+
if not (0 <= r < MAX_R and 0 <= c < MAX_C):
70+
return
71+
72+
if board[r][c] == "#":
73+
return
74+
75+
char = board[r][c]
76+
if char not in curr.children:
77+
return
78+
79+
post = curr.children[char]
80+
if post.data:
81+
result.add(post.data)
82+
83+
board[r][c] = "#"
84+
for dir_r, dir_c in DIRS:
85+
dfs(post, r + dir_r, c + dir_c, path + char)
86+
board[r][c] = char
87+
88+
result = set()
89+
for r in range(MAX_R):
90+
for c in range(MAX_C):
91+
if board[r][c] in trie.root.children:
92+
dfs(trie.root, r, c, "")
93+
94+
return list(result)
95+
96+
97+
class _LeetCodeTestCases(TestCase):
98+
def test_1(self):
99+
board = [["o", "a", "a", "n"], ["e", "t", "a", "e"], ["i", "h", "k", "r"], ["i", "f", "l", "v"]]
100+
words = ["oath","pea","eat","rain"]
101+
output = ["eat","oath"]
102+
self.assertEqual(Solution.findWords(Solution(), board, words), output)
103+
104+
def test_2(self):
105+
board = [["a","b"],["c","d"]]
106+
words = ["abcb"]
107+
output = []
108+
self.assertEqual(Solution.findWords(Solution(), board, words), output)
109+
110+
111+
if __name__ == '__main__':
112+
main()

0 commit comments

Comments
 (0)