From 4a48e02990fcfeecc81bc1efe3d9204ee5be62f2 Mon Sep 17 00:00:00 2001 From: Peter Chen Date: Wed, 8 Apr 2026 09:02:41 +0800 Subject: [PATCH] test: migrate LeetCode 208 to new directory structure with tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Migrate Trie (Prefix Tree) implementation from old directory structure to standardized problems/medium/ layout following project conventions. Code improvements: - Remove unnecessary is_end parameter from __init__ - Add type hints (dict[str, Trie]) for better clarity - Simplify variable naming (curr_node → curr, w → c) - Follow PEP 8 naming convention (startsWith → starts_with) Documentation: - Move complexity comments into proper docstrings - Update README.md: increment total count (87→88) and medium count (25→26) - Update docs/MEDIUM.md: add problem 208 entry Test coverage: - LeetCode official example test case --- README.md | 4 +- Trie/208. Implement Trie (Prefix Tree).py | 51 ----------------- docs/MEDIUM.md | 3 +- .../__init__.py | 0 .../solution.py | 55 +++++++++++++++++++ .../test_solution.py | 38 +++++++++++++ 6 files changed, 97 insertions(+), 54 deletions(-) delete mode 100644 Trie/208. Implement Trie (Prefix Tree).py create mode 100644 problems/medium/implement_trie_prefix_tree_208/__init__.py create mode 100644 problems/medium/implement_trie_prefix_tree_208/solution.py create mode 100644 problems/medium/implement_trie_prefix_tree_208/test_solution.py diff --git a/README.md b/README.md index 75421c4..84f029c 100644 --- a/README.md +++ b/README.md @@ -41,12 +41,12 @@ Each problem follows this structure: ## Solutions -📊 **Statistics**: 87 problems solved (migrated to new structure) +📊 **Statistics**: 88 problems solved (migrated to new structure) | Difficulty | Count | |------------|-------| | Easy | 61 | -| Medium | 25 | +| Medium | 26 | | Hard | 1 | ### Browse by Difficulty diff --git a/Trie/208. Implement Trie (Prefix Tree).py b/Trie/208. Implement Trie (Prefix Tree).py deleted file mode 100644 index b68de79..0000000 --- a/Trie/208. Implement Trie (Prefix Tree).py +++ /dev/null @@ -1,51 +0,0 @@ -# Hash Table, String, Design, Trie -class Trie: - - def __init__(self, is_end=False): - self.links = {} - self.is_end = is_end - - # Time complexity : O(m), where m is the key length. - # In each iteration of the algorithm, - # we either examine or create a node in the trie till we reach the end of the key. - # This takes only m operations. - - # Space complexity : O(m). - # In the worst case newly inserted key doesn't share - # a prefix with the the keys already inserted in the trie. - # We have to add m new nodes, which takes us O(m) space. - def insert(self, word: str) -> None: - curr_node = self - for w in word: - if w not in curr_node.links: - new_obj = Trie() - curr_node.links[w] = new_obj - curr_node = new_obj - else: - curr_node = curr_node.links[w] - curr_node.is_end = True - - # Time complexity : O(m) - # In each step of the algorithm we search for the next key character. - # In the worst case the algorithm performs m operations. - - # Space complexity : O(1) - def search(self, word: str) -> bool: - curr_node = self - for w in word: - if w not in curr_node.links: - return False - else: - curr_node = curr_node.links[w] - return curr_node.is_end - - # Time complexity : O(m) - # Space complexity : O(1) - def startsWith(self, prefix: str) -> bool: - curr_node = self - for w in prefix: - if w not in curr_node.links: - return False - else: - curr_node = curr_node.links[w] - return True diff --git a/docs/MEDIUM.md b/docs/MEDIUM.md index d85a3ff..145e246 100644 --- a/docs/MEDIUM.md +++ b/docs/MEDIUM.md @@ -1,6 +1,6 @@ # Medium Problems -Total: 25 problems solved +Total: 26 problems solved ## Solutions @@ -22,6 +22,7 @@ Total: 25 problems solved | 198 | [House Robber](https://leetcode.com/problems/house-robber/) | [solution.py](../problems/medium/house_robber_198/solution.py) | [test_solution.py](../problems/medium/house_robber_198/test_solution.py) | | 200 | [Number of Islands](https://leetcode.com/problems/number-of-islands/) | [solution.py](../problems/medium/number_of_islands_200/solution.py) | [test_solution.py](../problems/medium/number_of_islands_200/test_solution.py) | | 207 | [Course Schedule](https://leetcode.com/problems/course-schedule/) | [solution.py](../problems/medium/course_schedule_207/solution.py) | [test_solution.py](../problems/medium/course_schedule_207/test_solution.py) | +| 208 | [Implement Trie (Prefix Tree)](https://leetcode.com/problems/implement-trie-prefix-tree/) | [solution.py](../problems/medium/implement_trie_prefix_tree_208/solution.py) | [test_solution.py](../problems/medium/implement_trie_prefix_tree_208/test_solution.py) | | 230 | [Kth Smallest Element in a BST](https://leetcode.com/problems/kth-smallest-element-in-a-bst/) | [solution.py](../problems/medium/kth_smallest_element_in_a_bst_230/solution.py) | [test_solution.py](../problems/medium/kth_smallest_element_in_a_bst_230/test_solution.py) | | 235 | [Lowest Common Ancestor of a Binary Search Tree](https://leetcode.com/problems/lowest-common-ancestor-of-a-binary-search-tree/) | [solution.py](../problems/medium/lowest_common_ancestor_of_a_binary_search_tree_235/solution.py) | [test_solution.py](../problems/medium/lowest_common_ancestor_of_a_binary_search_tree_235/test_solution.py) | | 236 | [Lowest Common Ancestor of a Binary Tree](https://leetcode.com/problems/lowest-common-ancestor-of-a-binary-tree/) | [solution.py](../problems/medium/lowest_common_ancestor_of_a_binary_tree_236/solution.py) | [test_solution.py](../problems/medium/lowest_common_ancestor_of_a_binary_tree_236/test_solution.py) | diff --git a/problems/medium/implement_trie_prefix_tree_208/__init__.py b/problems/medium/implement_trie_prefix_tree_208/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/problems/medium/implement_trie_prefix_tree_208/solution.py b/problems/medium/implement_trie_prefix_tree_208/solution.py new file mode 100644 index 0000000..4cd559f --- /dev/null +++ b/problems/medium/implement_trie_prefix_tree_208/solution.py @@ -0,0 +1,55 @@ +# Tags: Hash Table, String, Design, Trie + + +class Trie: + + def __init__(self): + self.links: dict[str, Trie] = {} + self.is_end = False + + def insert(self, word: str) -> None: + """ + Time complexity : O(m), where m is the key(word) length. + In each iteration of the algorithm, + we either examine or create a node in the trie till we reach the end of the key. + This takes only m operations. + + Space complexity : O(m). + In the worst case newly inserted key doesn't share + a prefix with the keys already inserted in the trie. + We have to add m new nodes, which takes us O(m) space. + """ + curr = self + for c in word: + if c not in curr.links: + curr.links[c] = Trie() + curr = curr.links[c] + curr.is_end = True + + def search(self, word: str) -> bool: + """ + Time complexity : O(m) + In each step of the algorithm we search for the next key character. + In the worst case the algorithm performs m operations. + + Space complexity : O(1) + """ + curr = self + for c in word: + if c not in curr.links: + return False + curr = curr.links[c] + return curr.is_end + + def starts_with(self, prefix: str) -> bool: + """ + Time complexity : O(m) + + Space complexity : O(1) + """ + curr = self + for c in prefix: + if c not in curr.links: + return False + curr = curr.links[c] + return True diff --git a/problems/medium/implement_trie_prefix_tree_208/test_solution.py b/problems/medium/implement_trie_prefix_tree_208/test_solution.py new file mode 100644 index 0000000..9fc95f7 --- /dev/null +++ b/problems/medium/implement_trie_prefix_tree_208/test_solution.py @@ -0,0 +1,38 @@ +from .solution import Trie + + +class TestSolution: + + def call(self, methods, params, expected): + results = [] + obj = None + for method, param in zip(methods, params): + if method == "Trie": + obj = Trie() + results.append(None) + else: + result = getattr(obj, method)(*param) + results.append(result) + assert results == expected + + def test_example_1(self): + """ + Example 1: + Input: ["Trie", "insert", "search", "search", "starts_with", "insert", "search"] + [[], ["apple"], ["apple"], ["app"], ["app"], ["app"], ["app"]] + Output: [null, null, true, false, true, null, true] + + Explanation: + Trie trie = new Trie(); + trie.insert("apple"); + trie.search("apple"); // return True + trie.search("app"); // return False + trie.starts_with("app"); // return True + trie.insert("app"); + trie.search("app"); // return True + """ + self.call( + ["Trie", "insert", "search", "search", "starts_with", "insert", "search"], + [[], ["apple"], ["apple"], ["app"], ["app"], ["app"], ["app"]], + [None, None, True, False, True, None, True], + )