Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .amazonq/rules/problem-creation.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,13 @@ When creating JSON properties that use PascalCase (solution_class_name, test_cla
- Complex test setup with operation sequences
- Import custom class in test_imports

### Dict-based Tree Problems (Trie, etc.)

- Add `"solution_imports": "from leetcode_py.data_structures import DictTree"`
- Inherit from `DictTree[str]` for string-based trees like Trie
- Provides automatic visualization capabilities
- Use `dict[str, Any]` for internal tree structure

## Generation Commands

```bash
Expand Down
43 changes: 43 additions & 0 deletions .templates/leetcode/json/add_binary.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
{
"problem_name": "add_binary",
"solution_class_name": "Solution",
"problem_number": "67",
"problem_title": "Add Binary",
"difficulty": "Easy",
"topics": "Math, String, Bit Manipulation, Simulation",
"tags": ["grind-75"],
"readme_description": "Given two binary strings `a` and `b`, return *their sum as a binary string*.",
"readme_examples": [
{ "content": "```\nInput: a = \"11\", b = \"1\"\nOutput: \"100\"\n```" },
{ "content": "```\nInput: a = \"1010\", b = \"1011\"\nOutput: \"10101\"\n```" }
],
"readme_constraints": "- `1 <= a.length, b.length <= 10^4`\n- `a` and `b` consist only of `'0'` or `'1'` characters.\n- Each string does not contain leading zeros except for the zero itself.",
"readme_additional": "",
"solution_imports": "",
"solution_methods": [
{
"name": "add_binary",
"parameters": "a: str, b: str",
"return_type": "str",
"dummy_return": "\"\""
}
],
"test_imports": "import pytest\nfrom leetcode_py.test_utils import logged_test\nfrom .solution import Solution",
"test_class_name": "AddBinary",
"test_helper_methods": [
{ "name": "setup_method", "parameters": "", "body": "self.solution = Solution()" }
],
"test_methods": [
{
"name": "test_add_binary",
"parametrize": "a, b, expected",
"parametrize_typed": "a: str, b: str, expected: str",
"test_cases": "[('11', '1', '100'), ('1010', '1011', '10101'), ('0', '0', '0'), ('1', '1', '10'), ('1111', '1111', '11110')]",
"body": "result = self.solution.add_binary(a, b)\nassert result == expected"
}
],
"playground_imports": "from solution import Solution",
"playground_test_case": "# Example test case\na = '11'\nb = '1'\nexpected = '100'",
"playground_execution": "result = Solution().add_binary(a, b)\nresult",
"playground_assertion": "assert result == expected"
}
45 changes: 45 additions & 0 deletions .templates/leetcode/json/implement_trie_prefix_tree.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
{
"problem_name": "implement_trie_prefix_tree",
"solution_class_name": "Trie(DictTree[str])",
"problem_number": "208",
"problem_title": "Implement Trie (Prefix Tree)",
"difficulty": "Medium",
"topics": "Hash Table, String, Design, Trie",
"tags": ["grind-75"],
"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.",
"readme_examples": [
{
"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```"
}
],
"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`.",
"readme_additional": "",
"solution_imports": "from leetcode_py.data_structures import DictTree",
"solution_methods": [
{ "name": "__init__", "parameters": "", "return_type": "None", "dummy_return": "" },
{ "name": "insert", "parameters": "word: str", "return_type": "None", "dummy_return": "" },
{ "name": "search", "parameters": "word: str", "return_type": "bool", "dummy_return": "False" },
{
"name": "starts_with",
"parameters": "prefix: str",
"return_type": "bool",
"dummy_return": "False"
}
],
"test_imports": "import pytest\nfrom leetcode_py.test_utils import logged_test\nfrom .solution import Trie",
"test_class_name": "ImplementTriePrefixTree",
"test_helper_methods": [],
"test_methods": [
{
"name": "test_trie_operations",
"parametrize": "operations, inputs, expected",
"parametrize_typed": "operations: list[str], inputs: list[list[str]], expected: list[bool | None]",
"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])]",
"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"
}
],
"playground_imports": "from solution import Trie",
"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]",
"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",
"playground_assertion": "assert results == expected"
}
45 changes: 45 additions & 0 deletions .templates/leetcode/json/maximum_depth_of_binary_tree.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
{
"problem_name": "maximum_depth_of_binary_tree",
"solution_class_name": "Solution",
"problem_number": "104",
"problem_title": "Maximum Depth of Binary Tree",
"difficulty": "Easy",
"topics": "Tree, Depth-First Search, Breadth-First Search, Binary Tree",
"tags": ["grind-75"],
"readme_description": "Given the `root` of a binary tree, return *its maximum depth*.\n\nA binary tree's **maximum depth** is the number of nodes along the longest path from the root node down to the farthest leaf node.",
"readme_examples": [
{
"content": "![Example 1](https://assets.leetcode.com/uploads/2020/11/26/tmp-tree.jpg)\n\n```\nInput: root = [3,9,20,null,null,15,7]\nOutput: 3\n```"
},
{ "content": "```\nInput: root = [1,null,2]\nOutput: 2\n```" }
],
"readme_constraints": "- The number of nodes in the tree is in the range `[0, 10^4]`.\n- `-100 <= Node.val <= 100`",
"readme_additional": "",
"solution_imports": "from leetcode_py import TreeNode",
"solution_methods": [
{
"name": "max_depth",
"parameters": "root: TreeNode[int] | None",
"return_type": "int",
"dummy_return": "0"
}
],
"test_imports": "import pytest\nfrom leetcode_py.test_utils import logged_test\nfrom leetcode_py import TreeNode\nfrom .solution import Solution",
"test_class_name": "MaximumDepthOfBinaryTree",
"test_helper_methods": [
{ "name": "setup_method", "parameters": "", "body": "self.solution = Solution()" }
],
"test_methods": [
{
"name": "test_max_depth",
"parametrize": "root_list, expected",
"parametrize_typed": "root_list: list[int | None], expected: int",
"test_cases": "[([3, 9, 20, None, None, 15, 7], 3), ([1, None, 2], 2), ([], 0)]",
"body": "root = TreeNode.from_list(root_list)\nresult = self.solution.max_depth(root)\nassert result == expected"
}
],
"playground_imports": "from solution import Solution\nfrom leetcode_py import TreeNode",
"playground_test_case": "# Example test case\nroot_list = [3, 9, 20, None, None, 15, 7]\nexpected = 3",
"playground_execution": "root = TreeNode.from_list(root_list)\nresult = Solution().max_depth(root)\nresult",
"playground_assertion": "assert result == expected"
}
43 changes: 43 additions & 0 deletions .templates/leetcode/json/product_of_array_except_self.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
{
"problem_name": "product_of_array_except_self",
"solution_class_name": "Solution",
"problem_number": "238",
"problem_title": "Product of Array Except Self",
"difficulty": "Medium",
"topics": "Array, Prefix Sum",
"tags": ["grind-75"],
"readme_description": "Given an integer array `nums`, return an array `answer` such that `answer[i]` is equal to the product of all the elements of `nums` except `nums[i]`.\n\nThe product of any prefix or suffix of `nums` is guaranteed to fit in a 32-bit integer.\n\nYou must write an algorithm that runs in O(n) time and without using the division operation.",
"readme_examples": [
{ "content": "```\nInput: nums = [1,2,3,4]\nOutput: [24,12,8,6]\n```" },
{ "content": "```\nInput: nums = [-1,1,0,-3,3]\nOutput: [0,0,9,0,0]\n```" }
],
"readme_constraints": "- 2 <= nums.length <= 10^5\n- -30 <= nums[i] <= 30\n- The input is generated such that answer[i] is guaranteed to fit in a 32-bit integer.",
"readme_additional": "**Follow up:** Can you solve the problem in O(1) extra space complexity? (The output array does not count as extra space for space complexity analysis.)",
"solution_imports": "",
"solution_methods": [
{
"name": "product_except_self",
"parameters": "nums: list[int]",
"return_type": "list[int]",
"dummy_return": "[]"
}
],
"test_imports": "import pytest\nfrom leetcode_py.test_utils import logged_test\nfrom .solution import Solution",
"test_class_name": "ProductOfArrayExceptSelf",
"test_helper_methods": [
{ "name": "setup_method", "parameters": "", "body": "self.solution = Solution()" }
],
"test_methods": [
{
"name": "test_product_except_self",
"parametrize": "nums, expected",
"parametrize_typed": "nums: list[int], expected: list[int]",
"test_cases": "[([1, 2, 3, 4], [24, 12, 8, 6]), ([-1, 1, 0, -3, 3], [0, 0, 9, 0, 0]), ([2, 3, 4, 5], [60, 40, 30, 24])]",
"body": "result = self.solution.product_except_self(nums)\nassert result == expected"
}
],
"playground_imports": "from solution import Solution",
"playground_test_case": "# Example test case\nnums = [1, 2, 3, 4]\nexpected = [24, 12, 8, 6]",
"playground_execution": "result = Solution().product_except_self(nums)\nresult",
"playground_assertion": "assert result == expected"
}
51 changes: 51 additions & 0 deletions .templates/leetcode/json/string_to_integer_atoi.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
{
"problem_name": "string_to_integer_atoi",
"solution_class_name": "Solution",
"problem_number": "8",
"problem_title": "String to Integer (atoi)",
"difficulty": "Medium",
"topics": "String",
"tags": ["grind-75"],
"readme_description": "Implement the `my_atoi(string s)` function, which converts a string to a 32-bit signed integer.\n\nThe algorithm for `my_atoi(string s)` is as follows:\n\n1. **Whitespace**: Ignore any leading whitespace (` `).\n2. **Signedness**: Determine the sign by checking if the next character is `-` or `+`, assuming positivity if neither present.\n3. **Conversion**: Read the integer by skipping leading zeros until a non-digit character is encountered or the end of the string is reached. If no digits were read, then the result is 0.\n4. **Rounding**: If the integer is out of the 32-bit signed integer range `[-2^31, 2^31 - 1]`, then round the integer to remain in the range. Specifically, integers less than `-2^31` should be rounded to `-2^31`, and integers greater than `2^31 - 1` should be rounded to `2^31 - 1`.\n\nReturn the integer as the final result.",
"readme_examples": [
{
"content": "```\nInput: s = \"42\"\nOutput: 42\n```\n**Explanation:**\n```\nThe underlined characters are what is read in and the caret is the current reader position.\nStep 1: \"42\" (no characters read because there is no leading whitespace)\n ^\nStep 2: \"42\" (no characters read because there is neither a '-' nor '+')\n ^\nStep 3: \"42\" (\"42\" is read in)\n ^\n```"
},
{
"content": "```\nInput: s = \" -042\"\nOutput: -42\n```\n**Explanation:**\n```\nStep 1: \" -042\" (leading whitespace is read and ignored)\n ^\nStep 2: \" -042\" ('-' is read, so the result should be negative)\n ^\nStep 3: \" -042\" (\"042\" is read in, leading zeros ignored in the result)\n ^\n```"
},
{
"content": "```\nInput: s = \"1337c0d3\"\nOutput: 1337\n```\n**Explanation:**\n```\nStep 1: \"1337c0d3\" (no characters read because there is no leading whitespace)\n ^\nStep 2: \"1337c0d3\" (no characters read because there is neither a '-' nor '+')\n ^\nStep 3: \"1337c0d3\" (\"1337\" is read in; reading stops because the next character is a non-digit)\n ^\n```"
},
{
"content": "```\nInput: s = \"0-1\"\nOutput: 0\n```\n**Explanation:**\n```\nStep 1: \"0-1\" (no characters read because there is no leading whitespace)\n ^\nStep 2: \"0-1\" (no characters read because there is neither a '-' nor '+')\n ^\nStep 3: \"0-1\" (\"0\" is read in; reading stops because the next character is a non-digit)\n ^\n```"
},
{
"content": "```\nInput: s = \"words and 987\"\nOutput: 0\n```\n**Explanation:** Reading stops at the first non-digit character 'w'."
}
],
"readme_constraints": "- `0 <= s.length <= 200`\n- `s` consists of English letters (lower-case and upper-case), digits (0-9), ` `, `+`, `-`, and `.`.",
"readme_additional": "",
"solution_imports": "",
"solution_methods": [
{ "name": "my_atoi", "parameters": "s: str", "return_type": "int", "dummy_return": "0" }
],
"test_imports": "import pytest\nfrom leetcode_py.test_utils import logged_test\nfrom .solution import Solution",
"test_class_name": "StringToIntegerAtoi",
"test_helper_methods": [
{ "name": "setup_method", "parameters": "", "body": "self.solution = Solution()" }
],
"test_methods": [
{
"name": "test_my_atoi",
"parametrize": "s, expected",
"parametrize_typed": "s: str, expected: int",
"test_cases": "[('42', 42), (' -042', -42), ('1337c0d3', 1337), ('0-1', 0), ('words and 987', 0), ('', 0), (' ', 0), ('+1', 1), ('-1', -1), ('2147483647', 2147483647), ('-2147483648', -2147483648), ('2147483648', 2147483647), ('-2147483649', -2147483648)]",
"body": "result = self.solution.my_atoi(s)\nassert result == expected"
}
],
"playground_imports": "from solution import Solution",
"playground_test_case": "# Example test case\ns = '42'\nexpected = 42",
"playground_execution": "result = Solution().my_atoi(s)\nresult",
"playground_assertion": "assert result == expected"
}
4 changes: 2 additions & 2 deletions .templates/leetcode/{{cookiecutter.problem_name}}/solution.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ class {{cookiecutter.solution_class_name}}:
{%- for _, methods in cookiecutter._solution_methods | dictsort %}
{%- for method in methods %}
# Time: O(?)
# Space: O(?)
# Space: O(?){# TODO: add decorator // optional self. #}
def {{method.name}}(self, {{method.parameters}}) -> {{method.return_type}}:
# TODO: Implement {{method.name}}
# TODO: Implement {{method.name}}{# TODO: add body #}
return {{method.dummy_return}}

{%- endfor %}
Expand Down
2 changes: 1 addition & 1 deletion .templates/leetcode/{{cookiecutter.problem_name}}/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

class Test{{cookiecutter.test_class_name}}:
{%- for _, helper_methods in cookiecutter._test_helper_methods | dictsort %}
{%- for method in helper_methods %}
{%- for method in helper_methods %}{# TODO: add decorator // optional self. #}
def {{method.name}}(self{% if method.parameters %}, {{method.parameters}}{% endif %}):
{{method.body | indent(8, first=False)}}

Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
PYTHON_VERSION = 3.13
PROBLEM ?= maximum_profit_in_job_scheduling
PROBLEM ?= product_of_array_except_self
FORCE ?= 0
COMMA := ,

Expand Down
33 changes: 33 additions & 0 deletions leetcode/add_binary/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Add Binary

**Difficulty:** Easy
**Topics:** Math, String, Bit Manipulation, Simulation
**Tags:** grind-75

**LeetCode:** [Problem 67](https://leetcode.com/problems/add-binary/description/)

## Problem Description

Given two binary strings `a` and `b`, return _their sum as a binary string_.

## Examples

### Example 1:

```
Input: a = "11", b = "1"
Output: "100"
```

### Example 2:

```
Input: a = "1010", b = "1011"
Output: "10101"
```

## Constraints

- `1 <= a.length, b.length <= 10^4`
- `a` and `b` consist only of `'0'` or `'1'` characters.
- Each string does not contain leading zeros except for the zero itself.
Empty file added leetcode/add_binary/__init__.py
Empty file.
80 changes: 80 additions & 0 deletions leetcode/add_binary/playground.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"id": "imports",
"metadata": {},
"outputs": [],
"source": [
"from solution import Solution"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "setup",
"metadata": {},
"outputs": [],
"source": [
"# Example test case\n",
"a = \"11\"\n",
"b = \"1\"\n",
"expected = \"100\""
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "execute",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'100'"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"result = Solution().add_binary(a, b)\n",
"result"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "test",
"metadata": {},
"outputs": [],
"source": [
"assert result == expected"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "leetcode-py-py3.13",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.13.7"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
Loading
Loading