Skip to content

Commit 6f628c3

Browse files
committed
feat: completed example problems
1 parent 8dd2709 commit 6f628c3

36 files changed

+1661
-8
lines changed

.amazonq/plans/migrate_problems_to_new_template.md

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,15 @@ Migrate problems from `.templates/leetcode/json_old/` to `.templates/leetcode/js
44

55
## Migration Steps
66

7-
1. **Find next**: `python .amazonq/plans/find_next_problem.py`
8-
2. **Create JSON**: Analyze old format, create new template in `.templates/leetcode/json/`
9-
3. **Generate**: `make p-gen PROBLEM=<name>`
10-
4. **Lint**: `make p-lint PROBLEM=<name>` (fix JSON if fails, regenerate with `FORCE=1`)
11-
5. **Implement**: Copy solution from `leetcode_old/`
12-
6. **Test**: `make p-test PROBLEM=<name>`
13-
7. **Enhance tests**: If only 2-3 cases, add edge cases (update JSON → regenerate → lint → test)
14-
8. **Commit**: Save changes
7+
1. **Create JSON**: Analyze old format, create new template in `.templates/leetcode/json/`
8+
2. **Generate**: `make p-gen PROBLEM=<name>`
9+
3. **Lint**: `make p-lint PROBLEM=<name>` (fix JSON if fails, regenerate with `FORCE=1`)
10+
4. **Implement**: Look at `leetcode_old/` code - copy solution with all comments/notes and review test cases
11+
- **Important**: Re-copy solution after `p-gen` since it overwrites with TODO placeholders
12+
- **Multiple solutions**: If old code has alternative implementations (e.g., Solution, SolutionDFS, SolutionBFS),
13+
add parametrize to test all classes (see lru_cache as example)
14+
5. **Test**: `make p-test PROBLEM=<name>`
15+
6. **Enhance tests**: If only 2-3 cases, add edge cases (update JSON → regenerate → lint → test)
1516

1617
## Progress
1718

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
{
2+
"problem_name": "implement_trie_prefix_tree",
3+
"solution_class_name": "Trie(DictTree[str])",
4+
"problem_number": "208",
5+
"problem_title": "Implement Trie (Prefix Tree)",
6+
"difficulty": "Medium",
7+
"topics": "Hash Table, String, Design, Trie",
8+
"_tags": { "list": ["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+
"list": [
12+
{
13+
"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```"
14+
}
15+
]
16+
},
17+
"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`.",
18+
"readme_additional": "",
19+
"helpers_imports": "",
20+
"helpers_content": "",
21+
"helpers_run_name": "trie_operations",
22+
"helpers_run_signature": "(solution_class: type, operations: list[str], inputs: list[list[str]])",
23+
"helpers_run_body": " trie = None\n results: list[bool | None] = []\n for i, op in enumerate(operations):\n if op == 'Trie':\n trie = solution_class()\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]))\n return results, trie",
24+
"helpers_assert_name": "trie_operations",
25+
"helpers_assert_signature": "(result: list[bool | None], expected: list[bool | None]) -> bool",
26+
"helpers_assert_body": " assert result == expected\n return True",
27+
"solution_imports": "from leetcode_py.data_structures import DictTree, RecursiveDict",
28+
"solution_contents": "",
29+
"solution_class_content": "",
30+
"test_imports": "import pytest\nfrom leetcode_py.test_utils import logged_test\nfrom .helpers import assert_trie_operations, run_trie_operations\nfrom .solution import Trie",
31+
"test_content": "",
32+
"test_class_name": "ImplementTriePrefixTree",
33+
"test_class_content": "",
34+
"_solution_methods": {
35+
"list": [
36+
{
37+
"name": "__init__",
38+
"signature": "(self) -> None",
39+
"body": " super().__init__()\n self.root: RecursiveDict[str] = {}"
40+
},
41+
{
42+
"name": "insert",
43+
"signature": "(self, word: str) -> None",
44+
"body": " # TODO: Implement insert\n pass"
45+
},
46+
{
47+
"name": "search",
48+
"signature": "(self, word: str) -> bool",
49+
"body": " # TODO: Implement search\n return False"
50+
},
51+
{
52+
"name": "starts_with",
53+
"signature": "(self, prefix: str) -> bool",
54+
"body": " # TODO: Implement starts_with\n return False"
55+
}
56+
]
57+
},
58+
"_test_helper_methods": { "list": [] },
59+
"_test_methods": {
60+
"list": [
61+
{
62+
"name": "test_trie_operations",
63+
"signature": "(self, operations: list[str], inputs: list[list[str]], expected: list[bool | None])",
64+
"parametrize": "operations, inputs, expected",
65+
"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])]",
66+
"body": " result, _ = run_trie_operations(Trie, operations, inputs)\n assert_trie_operations(result, expected)"
67+
}
68+
]
69+
},
70+
"playground_imports": "from helpers import run_trie_operations, assert_trie_operations\nfrom solution import Trie",
71+
"playground_setup": "# 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]",
72+
"playground_run": "result, trie = run_trie_operations(Trie, operations, inputs)\nprint(result)\ntrie",
73+
"playground_assert": "assert_trie_operations(result, expected)"
74+
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
{
2+
"problem_name": "invert_binary_tree",
3+
"solution_class_name": "Solution",
4+
"problem_number": "226",
5+
"problem_title": "Invert Binary Tree",
6+
"difficulty": "Easy",
7+
"topics": "Tree, Depth-First Search, Breadth-First Search, Binary Tree",
8+
"_tags": { "list": ["grind-75"] },
9+
"readme_description": "Given the `root` of a binary tree, invert the tree, and return its root.",
10+
"_readme_examples": {
11+
"list": [
12+
{ "content": "```\nInput: root = [4,2,7,1,3,6,9]\nOutput: [4,7,2,9,6,3,1]\n```" },
13+
{ "content": "```\nInput: root = [2,1,3]\nOutput: [2,3,1]\n```" },
14+
{ "content": "```\nInput: root = []\nOutput: []\n```" }
15+
]
16+
},
17+
"readme_constraints": "- The number of nodes in the tree is in the range [0, 100]\n- -100 <= Node.val <= 100",
18+
"readme_additional": "",
19+
"helpers_imports": "from leetcode_py import TreeNode",
20+
"helpers_content": "",
21+
"helpers_run_name": "invert_tree",
22+
"helpers_run_signature": "(solution_class: type, root_list: list[int | None])",
23+
"helpers_run_body": " root = TreeNode[int].from_list(root_list)\n implementation = solution_class()\n return implementation.invert_tree(root)",
24+
"helpers_assert_name": "invert_tree",
25+
"helpers_assert_signature": "(result: TreeNode[int] | None, expected_list: list[int | None]) -> bool",
26+
"helpers_assert_body": " expected = TreeNode[int].from_list(expected_list)\n assert result == expected\n return True",
27+
"solution_imports": "from leetcode_py import TreeNode",
28+
"solution_contents": "",
29+
"solution_class_content": "",
30+
"test_imports": "import pytest\nfrom leetcode_py.test_utils import logged_test\nfrom .helpers import assert_invert_tree, run_invert_tree\nfrom .solution import Solution",
31+
"test_content": "",
32+
"test_class_name": "InvertBinaryTree",
33+
"test_class_content": " def setup_method(self):\n self.solution = Solution()",
34+
"_solution_methods": {
35+
"list": [
36+
{
37+
"name": "invert_tree",
38+
"signature": "(self, root: TreeNode[int] | None) -> TreeNode[int] | None",
39+
"body": " # TODO: Implement invert_tree\n return None"
40+
}
41+
]
42+
},
43+
"_test_helper_methods": {
44+
"list": [{ "name": "setup_method", "parameters": "", "body": "self.solution = Solution()" }]
45+
},
46+
"_test_methods": {
47+
"list": [
48+
{
49+
"name": "test_invert_tree",
50+
"signature": "(self, root_list: list[int | None], expected_list: list[int | None])",
51+
"parametrize": "root_list, expected_list",
52+
"test_cases": "[([4, 2, 7, 1, 3, 6, 9], [4, 7, 2, 9, 6, 3, 1]), ([2, 1, 3], [2, 3, 1]), ([], []), ([1], [1]), ([1, 2], [1, None, 2]), ([1, None, 2], [1, 2]), ([1, 2, 3, 4, 5], [1, 3, 2, None, None, 5, 4]), ([1, 2, 3, None, None, 4, 5], [1, 3, 2, 5, 4])]",
53+
"body": " result = run_invert_tree(Solution, root_list)\n assert_invert_tree(result, expected_list)"
54+
}
55+
]
56+
},
57+
"playground_imports": "from helpers import run_invert_tree, assert_invert_tree\nfrom solution import Solution\nfrom leetcode_py import TreeNode",
58+
"playground_setup": "# Example test case\nroot_list: list[int | None] = [4, 2, 7, 1, 3, 6, 9]\nexpected_list: list[int | None] = [4, 7, 2, 9, 6, 3, 1]",
59+
"playground_run": "result = run_invert_tree(Solution, root_list)\nresult",
60+
"playground_assert": "assert_invert_tree(result, expected_list)"
61+
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
{
2+
"problem_name": "lru_cache",
3+
"solution_class_name": "LRUCache",
4+
"problem_number": "146",
5+
"problem_title": "LRU Cache",
6+
"difficulty": "Medium",
7+
"topics": "Hash Table, Linked List, Design, Doubly-Linked List",
8+
"_tags": { "list": ["grind-75"] },
9+
"readme_description": "Design a data structure that follows the constraints of a Least Recently Used (LRU) cache.\n\nImplement the `LRUCache` class:\n\n- `LRUCache(int capacity)` Initialize the LRU cache with positive size capacity\n- `int get(int key)` Return the value of the key if the key exists, otherwise return -1\n- `void put(int key, int value)` Update the value of the key if the key exists. Otherwise, add the key-value pair to the cache. If the number of keys exceeds the capacity from this operation, evict the least recently used key\n\nThe functions `get` and `put` must each run in `O(1)` average time complexity.",
10+
"_readme_examples": {
11+
"list": [
12+
{
13+
"content": "```\nInput\n[\"LRUCache\", \"put\", \"put\", \"get\", \"put\", \"get\", \"put\", \"get\", \"get\", \"get\"]\n[[2], [1, 1], [2, 2], [1], [3, 3], [2], [4, 4], [1], [3], [4]]\nOutput\n[null, null, null, 1, null, -1, null, -1, 3, 4]\n\nExplanation\nLRUCache lRUCache = new LRUCache(2);\nlRUCache.put(1, 1); // cache is {1=1}\nlRUCache.put(2, 2); // cache is {1=1, 2=2}\nlRUCache.get(1); // return 1\nlRUCache.put(3, 3); // LRU key was 2, evicts key 2, cache is {1=1, 3=3}\nlRUCache.get(2); // returns -1 (not found)\nlRUCache.put(4, 4); // LRU key was 1, evicts key 1, cache is {4=4, 3=3}\nlRUCache.get(1); // return -1 (not found)\nlRUCache.get(3); // return 3\nlRUCache.get(4); // return 4\n```"
14+
}
15+
]
16+
},
17+
"readme_constraints": "- 1 <= capacity <= 3000\n- 0 <= key <= 10^4\n- 0 <= value <= 10^5\n- At most 2 * 10^5 calls will be made to get and put",
18+
"readme_additional": "",
19+
"helpers_imports": "",
20+
"helpers_content": "",
21+
"helpers_run_name": "lru_cache",
22+
"helpers_run_signature": "(solution_class: type, operations: list[str], inputs: list[list[int]])",
23+
"helpers_run_body": " cache = None\n results: list[int | None] = []\n for i, op in enumerate(operations):\n if op == 'LRUCache':\n cache = solution_class(inputs[i][0])\n results.append(None)\n elif op == 'get' and cache is not None:\n results.append(cache.get(inputs[i][0]))\n elif op == 'put' and cache is not None:\n cache.put(inputs[i][0], inputs[i][1])\n results.append(None)\n return results, cache",
24+
"helpers_assert_name": "lru_cache",
25+
"helpers_assert_signature": "(result: list[int | None], expected: list[int | None]) -> bool",
26+
"helpers_assert_body": " assert result == expected\n return True",
27+
"solution_imports": "",
28+
"solution_contents": "",
29+
"solution_class_content": "",
30+
"test_imports": "import pytest\nfrom leetcode_py.test_utils import logged_test\nfrom .helpers import assert_lru_cache, run_lru_cache\nfrom .solution import LRUCache",
31+
"test_content": "",
32+
"test_class_name": "LRUCache",
33+
"test_class_content": "",
34+
"_solution_methods": {
35+
"list": [
36+
{
37+
"name": "__init__",
38+
"signature": "(self, capacity: int) -> None",
39+
"body": " # TODO: Initialize LRU cache\n pass"
40+
},
41+
{
42+
"name": "get",
43+
"signature": "(self, key: int) -> int",
44+
"body": " # TODO: Implement get\n return -1"
45+
},
46+
{
47+
"name": "put",
48+
"signature": "(self, key: int, value: int) -> None",
49+
"body": " # TODO: Implement put\n pass"
50+
}
51+
]
52+
},
53+
"_test_helper_methods": { "list": [] },
54+
"_test_methods": {
55+
"list": [
56+
{
57+
"name": "test_lru_cache",
58+
"signature": "(self, operations: list[str], inputs: list[list[int]], expected: list[int | None])",
59+
"parametrize": "operations, inputs, expected",
60+
"test_cases": "[(['LRUCache', 'put', 'put', 'get', 'put', 'get', 'put', 'get', 'get', 'get'], [[2], [1, 1], [2, 2], [1], [3, 3], [2], [4, 4], [1], [3], [4]], [None, None, None, 1, None, -1, None, -1, 3, 4]), (['LRUCache', 'get', 'put', 'get', 'put', 'put', 'get', 'get'], [[2], [2], [2, 6], [1], [1, 5], [1, 2], [1], [2]], [None, -1, None, -1, None, None, 2, 6]), (['LRUCache', 'put', 'get', 'put', 'get', 'get'], [[1], [2, 1], [2], [3, 2], [2], [3]], [None, None, 1, None, -1, 2])]",
61+
"body": " result, _ = run_lru_cache(LRUCache, operations, inputs)\n assert_lru_cache(result, expected)"
62+
}
63+
]
64+
},
65+
"playground_imports": "from helpers import run_lru_cache, assert_lru_cache\nfrom solution import LRUCache",
66+
"playground_setup": "# Example test case\noperations = ['LRUCache', 'put', 'put', 'get', 'put', 'get', 'put', 'get', 'get', 'get']\ninputs = [[2], [1, 1], [2, 2], [1], [3, 3], [2], [4, 4], [1], [3], [4]]\nexpected = [None, None, None, 1, None, -1, None, -1, 3, 4]",
67+
"playground_run": "result, cache = run_lru_cache(LRUCache, operations, inputs)\nprint(result)\ncache",
68+
"playground_assert": "assert_lru_cache(result, expected)"
69+
}

0 commit comments

Comments
 (0)