Skip to content

Commit 73afc41

Browse files
committed
feat: add trie problem and dict_tree
1 parent 17f4324 commit 73afc41

File tree

10 files changed

+618
-1
lines changed

10 files changed

+618
-1
lines changed
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
{
2+
"problem_name": "implement_trie_prefix_tree",
3+
"solution_class_name": "Trie",
4+
"problem_number": "208",
5+
"problem_title": "Implement Trie (Prefix Tree)",
6+
"difficulty": "Medium",
7+
"topics": "Hash Table, String, Design, Trie",
8+
"tags": ["grind-75"],
9+
"readme_description": "A **trie** (pronounced as \"try\") or **prefix tree** is a tree data structure used to efficiently store and retrieve keys in a dataset of strings. There are various applications of this data structure, such as autocomplete and spellchecker.\n\nImplement the Trie class:\n\n- `Trie()` Initializes the trie object.\n- `void insert(String word)` Inserts the string `word` into the trie.\n- `boolean search(String word)` Returns `true` if the string `word` is in the trie (i.e., was inserted before), and `false` otherwise.\n- `boolean startsWith(String prefix)` Returns `true` if there is a previously inserted string `word` that has the prefix `prefix`, and `false` otherwise.",
10+
"readme_examples": [
11+
{
12+
"content": "```\nInput\n[\"Trie\", \"insert\", \"search\", \"search\", \"startsWith\", \"insert\", \"search\"]\n[[], [\"apple\"], [\"apple\"], [\"app\"], [\"app\"], [\"app\"], [\"app\"]]\nOutput\n[null, null, true, false, true, null, true]\n```\n\n**Explanation:**\n```python\ntrie = Trie()\ntrie.insert(\"apple\")\ntrie.search(\"apple\") # return True\ntrie.search(\"app\") # return False\ntrie.starts_with(\"app\") # return True\ntrie.insert(\"app\")\ntrie.search(\"app\") # return True\n```"
13+
}
14+
],
15+
"readme_constraints": "- `1 <= word.length, prefix.length <= 2000`\n- `word` and `prefix` consist only of lowercase English letters.\n- At most `3 * 10^4` calls **in total** will be made to `insert`, `search`, and `starts_with`.",
16+
"readme_additional": "",
17+
"solution_imports": "",
18+
"solution_methods": [
19+
{ "name": "__init__", "parameters": "", "return_type": "None", "dummy_return": "" },
20+
{ "name": "insert", "parameters": "word: str", "return_type": "None", "dummy_return": "" },
21+
{ "name": "search", "parameters": "word: str", "return_type": "bool", "dummy_return": "False" },
22+
{
23+
"name": "starts_with",
24+
"parameters": "prefix: str",
25+
"return_type": "bool",
26+
"dummy_return": "False"
27+
}
28+
],
29+
"test_imports": "import pytest\nfrom leetcode_py.test_utils import logged_test\nfrom .solution import Trie",
30+
"test_class_name": "ImplementTriePrefixTree",
31+
"test_helper_methods": [],
32+
"test_methods": [
33+
{
34+
"name": "test_trie_operations",
35+
"parametrize": "operations, inputs, expected",
36+
"parametrize_typed": "operations: list[str], inputs: list[list[str]], expected: list[bool | None]",
37+
"test_cases": "[(['Trie', 'insert', 'search', 'search', 'starts_with', 'insert', 'search'], [[], ['apple'], ['apple'], ['app'], ['app'], ['app'], ['app']], [None, None, True, False, True, None, True]), (['Trie', 'insert', 'insert', 'search', 'search', 'starts_with', 'starts_with'], [[], ['hello'], ['world'], ['hello'], ['hi'], ['hel'], ['wor']], [None, None, None, True, False, True, True]), (['Trie', 'insert', 'insert', 'search', 'search', 'starts_with', 'starts_with'], [[], ['a'], ['aa'], ['a'], ['aa'], ['a'], ['aa']], [None, None, None, True, True, True, True]), (['Trie', 'insert', 'search', 'starts_with', 'insert', 'search', 'starts_with'], [[], ['test'], ['testing'], ['test'], ['testing'], ['testing'], ['test']], [None, None, False, True, None, True, True]), (['Trie', 'search', 'starts_with'], [[], ['empty'], ['empty']], [None, False, False])]",
38+
"body": "trie: Trie | None = None\nresults: list[bool | None] = []\nfor i, op in enumerate(operations):\n if op == 'Trie':\n trie = Trie()\n results.append(None)\n elif op == 'insert' and trie is not None:\n trie.insert(inputs[i][0])\n results.append(None)\n elif op == 'search' and trie is not None:\n results.append(trie.search(inputs[i][0]))\n elif op == 'starts_with' and trie is not None:\n results.append(trie.starts_with(inputs[i][0]))\nassert results == expected"
39+
}
40+
],
41+
"playground_imports": "from solution import Trie",
42+
"playground_test_case": "# Example test case\noperations = ['Trie', 'insert', 'search', 'search', 'starts_with', 'insert', 'search']\ninputs = [[], ['apple'], ['apple'], ['app'], ['app'], ['app'], ['app']]\nexpected = [None, None, True, False, True, None, True]",
43+
"playground_execution": "trie = None\nresults: list[bool | None] = []\nfor i, op in enumerate(operations):\n if op == 'Trie':\n trie = Trie()\n results.append(None)\n elif op == 'insert' and trie is not None:\n trie.insert(inputs[i][0])\n results.append(None)\n elif op == 'search' and trie is not None:\n results.append(trie.search(inputs[i][0]))\n elif op == 'starts_with' and trie is not None:\n results.append(trie.starts_with(inputs[i][0]))\nresults",
44+
"playground_assertion": "assert results == expected"
45+
}

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
PYTHON_VERSION = 3.13
2-
PROBLEM ?= maximum_profit_in_job_scheduling
2+
PROBLEM ?= implement_trie_prefix_tree
33
FORCE ?= 0
44
COMMA := ,
55

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# Implement Trie (Prefix Tree)
2+
3+
**Difficulty:** Medium
4+
**Topics:** Hash Table, String, Design, Trie
5+
**Tags:** grind-75
6+
7+
**LeetCode:** [Problem 208](https://leetcode.com/problems/implement-trie-prefix-tree/description/)
8+
9+
## Problem Description
10+
11+
A **trie** (pronounced as "try") or **prefix tree** is a tree data structure used to efficiently store and retrieve keys in a dataset of strings. There are various applications of this data structure, such as autocomplete and spellchecker.
12+
13+
Implement the Trie class:
14+
15+
- `Trie()` Initializes the trie object.
16+
- `void insert(String word)` Inserts the string `word` into the trie.
17+
- `boolean search(String word)` Returns `true` if the string `word` is in the trie (i.e., was inserted before), and `false` otherwise.
18+
- `boolean startsWith(String prefix)` Returns `true` if there is a previously inserted string `word` that has the prefix `prefix`, and `false` otherwise.
19+
20+
## Examples
21+
22+
### Example 1:
23+
24+
```
25+
Input
26+
["Trie", "insert", "search", "search", "startsWith", "insert", "search"]
27+
[[], ["apple"], ["apple"], ["app"], ["app"], ["app"], ["app"]]
28+
Output
29+
[null, null, true, false, true, null, true]
30+
```
31+
32+
**Explanation:**
33+
34+
```python
35+
trie = Trie()
36+
trie.insert("apple")
37+
trie.search("apple") # return True
38+
trie.search("app") # return False
39+
trie.starts_with("app") # return True
40+
trie.insert("app")
41+
trie.search("app") # return True
42+
```
43+
44+
## Constraints
45+
46+
- `1 <= word.length, prefix.length <= 2000`
47+
- `word` and `prefix` consist only of lowercase English letters.
48+
- At most `3 * 10^4` calls **in total** will be made to `insert`, `search`, and `starts_with`.

leetcode/implement_trie_prefix_tree/__init__.py

Whitespace-only changes.
Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "code",
5+
"execution_count": 1,
6+
"id": "imports",
7+
"metadata": {},
8+
"outputs": [],
9+
"source": [
10+
"from solution import Trie"
11+
]
12+
},
13+
{
14+
"cell_type": "code",
15+
"execution_count": 2,
16+
"id": "setup",
17+
"metadata": {},
18+
"outputs": [],
19+
"source": [
20+
"# Example test case\n",
21+
"operations = [\"Trie\", \"insert\", \"search\", \"search\", \"starts_with\", \"insert\", \"search\"]\n",
22+
"inputs = [[], [\"apple\"], [\"apple\"], [\"app\"], [\"app\"], [\"app\"], [\"app\"]]\n",
23+
"expected = [None, None, True, False, True, None, True]"
24+
]
25+
},
26+
{
27+
"cell_type": "code",
28+
"execution_count": 3,
29+
"id": "execute",
30+
"metadata": {},
31+
"outputs": [
32+
{
33+
"data": {
34+
"text/plain": [
35+
"[None, None, True, False, True, None, True]"
36+
]
37+
},
38+
"execution_count": 3,
39+
"metadata": {},
40+
"output_type": "execute_result"
41+
}
42+
],
43+
"source": [
44+
"trie = None\n",
45+
"results: list[bool | None] = []\n",
46+
"for i, op in enumerate(operations):\n",
47+
" if op == \"Trie\":\n",
48+
" trie = Trie()\n",
49+
" results.append(None)\n",
50+
" elif op == \"insert\" and trie is not None:\n",
51+
" trie.insert(inputs[i][0])\n",
52+
" results.append(None)\n",
53+
" elif op == \"search\" and trie is not None:\n",
54+
" results.append(trie.search(inputs[i][0]))\n",
55+
" elif op == \"starts_with\" and trie is not None:\n",
56+
" results.append(trie.starts_with(inputs[i][0]))\n",
57+
"results"
58+
]
59+
},
60+
{
61+
"cell_type": "code",
62+
"execution_count": 4,
63+
"id": "8d00661e",
64+
"metadata": {},
65+
"outputs": [
66+
{
67+
"data": {
68+
"text/html": [
69+
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n",
70+
"<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n",
71+
" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n",
72+
"<!-- Generated by graphviz version 13.1.2 (20250808.2320)\n",
73+
" -->\n",
74+
"<!-- Pages: 1 -->\n",
75+
"<svg width=\"136pt\" height=\"476pt\"\n",
76+
" viewBox=\"0.00 0.00 136.00 476.00\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n",
77+
"<g id=\"graph0\" class=\"graph\" transform=\"scale(1 1) rotate(0) translate(4 472)\">\n",
78+
"<polygon fill=\"white\" stroke=\"none\" points=\"-4,4 -4,-472 132,-472 132,4 -4,4\"/>\n",
79+
"<!-- root -->\n",
80+
"<g id=\"node1\" class=\"node\">\n",
81+
"<title>root</title>\n",
82+
"<path fill=\"lightblue\" stroke=\"black\" d=\"M78.5,-468C78.5,-468 48.5,-468 48.5,-468 42.5,-468 36.5,-462 36.5,-456 36.5,-456 36.5,-444 36.5,-444 36.5,-438 42.5,-432 48.5,-432 48.5,-432 78.5,-432 78.5,-432 84.5,-432 90.5,-438 90.5,-444 90.5,-444 90.5,-456 90.5,-456 90.5,-462 84.5,-468 78.5,-468\"/>\n",
83+
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"63.5\" y=\"-444.95\" font-family=\"Times,serif\" font-size=\"14.00\">root</text>\n",
84+
"</g>\n",
85+
"<!-- root_0 -->\n",
86+
"<g id=\"node2\" class=\"node\">\n",
87+
"<title>root_0</title>\n",
88+
"<path fill=\"lightblue\" stroke=\"black\" d=\"M78.5,-396C78.5,-396 48.5,-396 48.5,-396 42.5,-396 36.5,-390 36.5,-384 36.5,-384 36.5,-372 36.5,-372 36.5,-366 42.5,-360 48.5,-360 48.5,-360 78.5,-360 78.5,-360 84.5,-360 90.5,-366 90.5,-372 90.5,-372 90.5,-384 90.5,-384 90.5,-390 84.5,-396 78.5,-396\"/>\n",
89+
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"63.5\" y=\"-372.95\" font-family=\"Times,serif\" font-size=\"14.00\">a</text>\n",
90+
"</g>\n",
91+
"<!-- root&#45;&gt;root_0 -->\n",
92+
"<g id=\"edge1\" class=\"edge\">\n",
93+
"<title>root&#45;&gt;root_0</title>\n",
94+
"<path fill=\"none\" stroke=\"black\" d=\"M63.5,-431.7C63.5,-424.41 63.5,-415.73 63.5,-407.54\"/>\n",
95+
"<polygon fill=\"black\" stroke=\"black\" points=\"67,-407.62 63.5,-397.62 60,-407.62 67,-407.62\"/>\n",
96+
"</g>\n",
97+
"<!-- root_0_0 -->\n",
98+
"<g id=\"node3\" class=\"node\">\n",
99+
"<title>root_0_0</title>\n",
100+
"<path fill=\"lightblue\" stroke=\"black\" d=\"M78.5,-324C78.5,-324 48.5,-324 48.5,-324 42.5,-324 36.5,-318 36.5,-312 36.5,-312 36.5,-300 36.5,-300 36.5,-294 42.5,-288 48.5,-288 48.5,-288 78.5,-288 78.5,-288 84.5,-288 90.5,-294 90.5,-300 90.5,-300 90.5,-312 90.5,-312 90.5,-318 84.5,-324 78.5,-324\"/>\n",
101+
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"63.5\" y=\"-300.95\" font-family=\"Times,serif\" font-size=\"14.00\">p</text>\n",
102+
"</g>\n",
103+
"<!-- root_0&#45;&gt;root_0_0 -->\n",
104+
"<g id=\"edge2\" class=\"edge\">\n",
105+
"<title>root_0&#45;&gt;root_0_0</title>\n",
106+
"<path fill=\"none\" stroke=\"black\" d=\"M63.5,-359.7C63.5,-352.41 63.5,-343.73 63.5,-335.54\"/>\n",
107+
"<polygon fill=\"black\" stroke=\"black\" points=\"67,-335.62 63.5,-325.62 60,-335.62 67,-335.62\"/>\n",
108+
"</g>\n",
109+
"<!-- root_0_0_0 -->\n",
110+
"<g id=\"node4\" class=\"node\">\n",
111+
"<title>root_0_0_0</title>\n",
112+
"<path fill=\"lightblue\" stroke=\"black\" d=\"M78.5,-252C78.5,-252 48.5,-252 48.5,-252 42.5,-252 36.5,-246 36.5,-240 36.5,-240 36.5,-228 36.5,-228 36.5,-222 42.5,-216 48.5,-216 48.5,-216 78.5,-216 78.5,-216 84.5,-216 90.5,-222 90.5,-228 90.5,-228 90.5,-240 90.5,-240 90.5,-246 84.5,-252 78.5,-252\"/>\n",
113+
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"63.5\" y=\"-228.95\" font-family=\"Times,serif\" font-size=\"14.00\">p</text>\n",
114+
"</g>\n",
115+
"<!-- root_0_0&#45;&gt;root_0_0_0 -->\n",
116+
"<g id=\"edge3\" class=\"edge\">\n",
117+
"<title>root_0_0&#45;&gt;root_0_0_0</title>\n",
118+
"<path fill=\"none\" stroke=\"black\" d=\"M63.5,-287.7C63.5,-280.41 63.5,-271.73 63.5,-263.54\"/>\n",
119+
"<polygon fill=\"black\" stroke=\"black\" points=\"67,-263.62 63.5,-253.62 60,-263.62 67,-263.62\"/>\n",
120+
"</g>\n",
121+
"<!-- root_0_0_0_0 -->\n",
122+
"<g id=\"node5\" class=\"node\">\n",
123+
"<title>root_0_0_0_0</title>\n",
124+
"<path fill=\"lightblue\" stroke=\"black\" d=\"M42.5,-180C42.5,-180 12.5,-180 12.5,-180 6.5,-180 0.5,-174 0.5,-168 0.5,-168 0.5,-156 0.5,-156 0.5,-150 6.5,-144 12.5,-144 12.5,-144 42.5,-144 42.5,-144 48.5,-144 54.5,-150 54.5,-156 54.5,-156 54.5,-168 54.5,-168 54.5,-174 48.5,-180 42.5,-180\"/>\n",
125+
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"27.5\" y=\"-156.95\" font-family=\"Times,serif\" font-size=\"14.00\">l</text>\n",
126+
"</g>\n",
127+
"<!-- root_0_0_0&#45;&gt;root_0_0_0_0 -->\n",
128+
"<g id=\"edge4\" class=\"edge\">\n",
129+
"<title>root_0_0_0&#45;&gt;root_0_0_0_0</title>\n",
130+
"<path fill=\"none\" stroke=\"black\" d=\"M54.6,-215.7C50.63,-207.98 45.87,-198.71 41.44,-190.11\"/>\n",
131+
"<polygon fill=\"black\" stroke=\"black\" points=\"44.67,-188.74 36.99,-181.45 38.45,-191.94 44.67,-188.74\"/>\n",
132+
"</g>\n",
133+
"<!-- root_0_0_0_leaf_1 -->\n",
134+
"<g id=\"node8\" class=\"node\">\n",
135+
"<title>root_0_0_0_leaf_1</title>\n",
136+
"<path fill=\"lightgreen\" stroke=\"black\" d=\"M116,-180C116,-180 85,-180 85,-180 79,-180 73,-174 73,-168 73,-168 73,-156 73,-156 73,-150 79,-144 85,-144 85,-144 116,-144 116,-144 122,-144 128,-150 128,-156 128,-156 128,-168 128,-168 128,-174 122,-180 116,-180\"/>\n",
137+
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"100.5\" y=\"-156.95\" font-family=\"Times,serif\" font-size=\"14.00\">#: True</text>\n",
138+
"</g>\n",
139+
"<!-- root_0_0_0&#45;&gt;root_0_0_0_leaf_1 -->\n",
140+
"<g id=\"edge7\" class=\"edge\">\n",
141+
"<title>root_0_0_0&#45;&gt;root_0_0_0_leaf_1</title>\n",
142+
"<path fill=\"none\" stroke=\"black\" d=\"M72.65,-215.7C76.72,-207.98 81.62,-198.71 86.17,-190.11\"/>\n",
143+
"<polygon fill=\"black\" stroke=\"black\" points=\"89.17,-191.92 90.75,-181.44 82.98,-188.65 89.17,-191.92\"/>\n",
144+
"</g>\n",
145+
"<!-- root_0_0_0_0_0 -->\n",
146+
"<g id=\"node6\" class=\"node\">\n",
147+
"<title>root_0_0_0_0_0</title>\n",
148+
"<path fill=\"lightblue\" stroke=\"black\" d=\"M42.5,-108C42.5,-108 12.5,-108 12.5,-108 6.5,-108 0.5,-102 0.5,-96 0.5,-96 0.5,-84 0.5,-84 0.5,-78 6.5,-72 12.5,-72 12.5,-72 42.5,-72 42.5,-72 48.5,-72 54.5,-78 54.5,-84 54.5,-84 54.5,-96 54.5,-96 54.5,-102 48.5,-108 42.5,-108\"/>\n",
149+
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"27.5\" y=\"-84.95\" font-family=\"Times,serif\" font-size=\"14.00\">e</text>\n",
150+
"</g>\n",
151+
"<!-- root_0_0_0_0&#45;&gt;root_0_0_0_0_0 -->\n",
152+
"<g id=\"edge5\" class=\"edge\">\n",
153+
"<title>root_0_0_0_0&#45;&gt;root_0_0_0_0_0</title>\n",
154+
"<path fill=\"none\" stroke=\"black\" d=\"M27.5,-143.7C27.5,-136.41 27.5,-127.73 27.5,-119.54\"/>\n",
155+
"<polygon fill=\"black\" stroke=\"black\" points=\"31,-119.62 27.5,-109.62 24,-119.62 31,-119.62\"/>\n",
156+
"</g>\n",
157+
"<!-- root_0_0_0_0_0_leaf_0 -->\n",
158+
"<g id=\"node7\" class=\"node\">\n",
159+
"<title>root_0_0_0_0_0_leaf_0</title>\n",
160+
"<path fill=\"lightgreen\" stroke=\"black\" d=\"M43,-36C43,-36 12,-36 12,-36 6,-36 0,-30 0,-24 0,-24 0,-12 0,-12 0,-6 6,0 12,0 12,0 43,0 43,0 49,0 55,-6 55,-12 55,-12 55,-24 55,-24 55,-30 49,-36 43,-36\"/>\n",
161+
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"27.5\" y=\"-12.95\" font-family=\"Times,serif\" font-size=\"14.00\">#: True</text>\n",
162+
"</g>\n",
163+
"<!-- root_0_0_0_0_0&#45;&gt;root_0_0_0_0_0_leaf_0 -->\n",
164+
"<g id=\"edge6\" class=\"edge\">\n",
165+
"<title>root_0_0_0_0_0&#45;&gt;root_0_0_0_0_0_leaf_0</title>\n",
166+
"<path fill=\"none\" stroke=\"black\" d=\"M27.5,-71.7C27.5,-64.41 27.5,-55.73 27.5,-47.54\"/>\n",
167+
"<polygon fill=\"black\" stroke=\"black\" points=\"31,-47.62 27.5,-37.62 24,-47.62 31,-47.62\"/>\n",
168+
"</g>\n",
169+
"</g>\n",
170+
"</svg>\n"
171+
],
172+
"text/plain": [
173+
"<solution.Trie at 0x1043da270>"
174+
]
175+
},
176+
"execution_count": 4,
177+
"metadata": {},
178+
"output_type": "execute_result"
179+
}
180+
],
181+
"source": [
182+
"trie"
183+
]
184+
},
185+
{
186+
"cell_type": "code",
187+
"execution_count": 5,
188+
"id": "test",
189+
"metadata": {},
190+
"outputs": [],
191+
"source": [
192+
"assert results == expected"
193+
]
194+
}
195+
],
196+
"metadata": {
197+
"kernelspec": {
198+
"display_name": "leetcode-py-py3.13",
199+
"language": "python",
200+
"name": "python3"
201+
},
202+
"language_info": {
203+
"codemirror_mode": {
204+
"name": "ipython",
205+
"version": 3
206+
},
207+
"file_extension": ".py",
208+
"mimetype": "text/x-python",
209+
"name": "python",
210+
"nbconvert_exporter": "python",
211+
"pygments_lexer": "ipython3",
212+
"version": "3.13.7"
213+
}
214+
},
215+
"nbformat": 4,
216+
"nbformat_minor": 5
217+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
from typing import Any
2+
3+
from leetcode_py.data_structures import DictTree
4+
5+
6+
class Trie(DictTree[str]):
7+
END_OF_WORD = "#"
8+
9+
# Time: O(1)
10+
# Space: O(1)
11+
def __init__(self) -> None:
12+
self.root: dict[str, Any] = {}
13+
14+
# Time: O(m) where m is word length
15+
# Space: O(m)
16+
def insert(self, word: str) -> None:
17+
node = self.root
18+
for char in word:
19+
if char not in node:
20+
node[char] = {}
21+
node = node[char]
22+
node[self.END_OF_WORD] = True # End of word marker
23+
24+
# Time: O(m) where m is word length
25+
# Space: O(1)
26+
def search(self, word: str) -> bool:
27+
node = self.root
28+
for char in word:
29+
if char not in node:
30+
return False
31+
node = node[char]
32+
return self.END_OF_WORD in node
33+
34+
# Time: O(m) where m is prefix length
35+
# Space: O(1)
36+
def starts_with(self, prefix: str) -> bool:
37+
node = self.root
38+
for char in prefix:
39+
if char not in node:
40+
return False
41+
node = node[char]
42+
return True

0 commit comments

Comments
 (0)