Skip to content

Commit b600b19

Browse files
committed
feat: add problem same_tree
1 parent a598232 commit b600b19

File tree

11 files changed

+222
-32
lines changed

11 files changed

+222
-32
lines changed

.cursor/.dev/update_tags.py

Lines changed: 1 addition & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -8,36 +8,7 @@
88
sys.path.append(str(Path(__file__).parent.parent.parent))
99
from problem_lists import available_lists
1010

11-
# Import existing function to reuse the tag resolution logic
12-
try:
13-
from leetcode_py.cli.utils.problem_finder import find_problems_by_tag
14-
except ImportError:
15-
# Fallback if import fails
16-
def find_problems_by_tag(tag: str) -> list[str]:
17-
"""Fallback function to find problems by tag."""
18-
try:
19-
import json5
20-
21-
tags_path = (
22-
Path(__file__).parent.parent.parent
23-
/ "leetcode_py/cli/resources/leetcode/json/tags.json5"
24-
)
25-
with open(tags_path, "r") as f:
26-
tags_data = json5.load(f)
27-
28-
problems = []
29-
tag_items = tags_data.get(tag, [])
30-
31-
for item in tag_items:
32-
if isinstance(item, dict) and "tag" in item:
33-
# Resolve tag reference recursively
34-
referenced_problems = find_problems_by_tag(item["tag"])
35-
problems.extend(referenced_problems)
36-
elif isinstance(item, str):
37-
problems.append(item)
38-
return problems
39-
except Exception:
40-
return []
11+
from leetcode_py.cli.utils.problem_finder import find_problems_by_tag
4112

4213

4314
def get_existing_problems():

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 ?= jump_game
2+
PROBLEM ?= same_tree
33
FORCE ?= 0
44
COMMA := ,
55

leetcode/same_tree/README.md

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# Same Tree
2+
3+
**Difficulty:** Easy
4+
**Topics:** Tree, Depth-First Search, Breadth-First Search, Binary Tree
5+
**Tags:** blind-75
6+
7+
**LeetCode:** [Problem 100](https://leetcode.com/problems/same-tree/description/)
8+
9+
## Problem Description
10+
11+
Given the roots of two binary trees `p` and `q`, write a function to check if they are the same or not.
12+
13+
Two binary trees are considered the same if they are structurally identical, and the nodes have the same value.
14+
15+
## Examples
16+
17+
### Example 1:
18+
19+
![Example 1](https://assets.leetcode.com/uploads/2020/12/20/ex1.jpg)
20+
21+
```
22+
Input: p = [1,2,3], q = [1,2,3]
23+
Output: true
24+
```
25+
26+
### Example 2:
27+
28+
![Example 2](https://assets.leetcode.com/uploads/2020/12/20/ex2.jpg)
29+
30+
```
31+
Input: p = [1,2], q = [1,null,2]
32+
Output: false
33+
```
34+
35+
### Example 3:
36+
37+
![Example 3](https://assets.leetcode.com/uploads/2020/12/20/ex3.jpg)
38+
39+
```
40+
Input: p = [1,2,1], q = [1,1,2]
41+
Output: false
42+
```
43+
44+
## Constraints
45+
46+
- The number of nodes in both trees is in the range [0, 100].
47+
- -10^4 <= Node.val <= 10^4

leetcode/same_tree/__init__.py

Whitespace-only changes.

leetcode/same_tree/helpers.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
from leetcode_py import TreeNode
2+
3+
4+
def run_is_same_tree(solution_class: type, p_list: list[int | None], q_list: list[int | None]):
5+
p = TreeNode[int].from_list(p_list)
6+
q = TreeNode[int].from_list(q_list)
7+
implementation = solution_class()
8+
return implementation.is_same_tree(p, q)
9+
10+
11+
def assert_is_same_tree(result: bool, expected: bool) -> bool:
12+
assert result == expected
13+
return True

leetcode/same_tree/playground.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# ---
2+
# jupyter:
3+
# jupytext:
4+
# text_representation:
5+
# extension: .py
6+
# format_name: percent
7+
# format_version: '1.3'
8+
# jupytext_version: 1.17.3
9+
# kernelspec:
10+
# display_name: leetcode-py-py3.13
11+
# language: python
12+
# name: python3
13+
# ---
14+
15+
# %%
16+
from helpers import assert_is_same_tree, run_is_same_tree
17+
from solution import Solution
18+
19+
# %%
20+
# Example test case
21+
p_list: list[int | None] = [1, 2, 3]
22+
q_list: list[int | None] = [1, 2, 3]
23+
expected = True
24+
25+
# %%
26+
result = run_is_same_tree(Solution, p_list, q_list)
27+
result
28+
29+
# %%
30+
assert_is_same_tree(result, expected)

leetcode/same_tree/solution.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
from leetcode_py import TreeNode
2+
3+
4+
class Solution:
5+
6+
# Time: O(min(m, n)) where m and n are the number of nodes in the two trees
7+
# Space: O(min(m, n)) for the recursion stack
8+
def is_same_tree(self, p: TreeNode[int] | None, q: TreeNode[int] | None) -> bool:
9+
# Base case: both nodes are None
10+
if p is None and q is None:
11+
return True
12+
13+
# Base case: one node is None, the other is not
14+
if p is None or q is None:
15+
return False
16+
17+
# Check if current nodes have the same value
18+
if p.val != q.val:
19+
return False
20+
21+
# Recursively check left and right subtrees
22+
return self.is_same_tree(p.left, q.left) and self.is_same_tree(p.right, q.right)
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import pytest
2+
3+
from leetcode_py import logged_test
4+
5+
from .helpers import assert_is_same_tree, run_is_same_tree
6+
from .solution import Solution
7+
8+
9+
class TestSameTree:
10+
def setup_method(self):
11+
self.solution = Solution()
12+
13+
@logged_test
14+
@pytest.mark.parametrize(
15+
"p_list, q_list, expected",
16+
[
17+
([1, 2, 3], [1, 2, 3], True),
18+
([1, 2], [1, None, 2], False),
19+
([1, 2, 1], [1, 1, 2], False),
20+
([], [], True),
21+
([1], [1], True),
22+
([1], [2], False),
23+
([1, None, 2], [1, 2], False),
24+
([1, 2, 3, 4, 5], [1, 2, 3, 4, 5], True),
25+
([1, 2, 3, 4, 5], [1, 2, 3, 4, 6], False),
26+
([1, 2, 3, None, 4], [1, 2, 3, None, 4], True),
27+
([1, 2, 3, None, 4], [1, 2, 3, 4, None], False),
28+
],
29+
)
30+
def test_is_same_tree(self, p_list: list[int | None], q_list: list[int | None], expected: bool):
31+
result = run_is_same_tree(Solution, p_list, q_list)
32+
assert_is_same_tree(result, expected)
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
{
2+
"problem_name": "same_tree",
3+
"solution_class_name": "Solution",
4+
"problem_number": "100",
5+
"problem_title": "Same Tree",
6+
"difficulty": "Easy",
7+
"topics": "Tree, Depth-First Search, Breadth-First Search, Binary Tree",
8+
"_tags": { "list": ["blind-75"] },
9+
"readme_description": "Given the roots of two binary trees `p` and `q`, write a function to check if they are the same or not.\n\nTwo binary trees are considered the same if they are structurally identical, and the nodes have the same value.",
10+
"_readme_examples": {
11+
"list": [
12+
{
13+
"content": "![Example 1](https://assets.leetcode.com/uploads/2020/12/20/ex1.jpg)\n\n```\nInput: p = [1,2,3], q = [1,2,3]\nOutput: true\n```"
14+
},
15+
{
16+
"content": "![Example 2](https://assets.leetcode.com/uploads/2020/12/20/ex2.jpg)\n\n```\nInput: p = [1,2], q = [1,null,2]\nOutput: false\n```"
17+
},
18+
{
19+
"content": "![Example 3](https://assets.leetcode.com/uploads/2020/12/20/ex3.jpg)\n\n```\nInput: p = [1,2,1], q = [1,1,2]\nOutput: false\n```"
20+
}
21+
]
22+
},
23+
"readme_constraints": "- The number of nodes in both trees is in the range [0, 100].\n- -10^4 <= Node.val <= 10^4",
24+
"readme_additional": "",
25+
"helpers_imports": "from leetcode_py import TreeNode",
26+
"helpers_content": "",
27+
"helpers_run_name": "is_same_tree",
28+
"helpers_run_signature": "(solution_class: type, p_list: list[int | None], q_list: list[int | None])",
29+
"helpers_run_body": " p = TreeNode[int].from_list(p_list)\n q = TreeNode[int].from_list(q_list)\n implementation = solution_class()\n return implementation.is_same_tree(p, q)",
30+
"helpers_assert_name": "is_same_tree",
31+
"helpers_assert_signature": "(result: bool, expected: bool) -> bool",
32+
"helpers_assert_body": " assert result == expected\n return True",
33+
"solution_imports": "from leetcode_py import TreeNode",
34+
"solution_contents": "",
35+
"solution_class_content": "",
36+
"test_imports": "import pytest\nfrom leetcode_py import logged_test\nfrom .helpers import assert_is_same_tree, run_is_same_tree\nfrom .solution import Solution",
37+
"test_content": "",
38+
"test_class_name": "SameTree",
39+
"test_class_content": " def setup_method(self):\n self.solution = Solution()",
40+
"_solution_methods": {
41+
"list": [
42+
{
43+
"name": "is_same_tree",
44+
"signature": "(self, p: TreeNode[int] | None, q: TreeNode[int] | None) -> bool",
45+
"body": " # TODO: Implement is_same_tree\n return False"
46+
}
47+
]
48+
},
49+
"_test_helper_methods": {
50+
"list": [{ "name": "setup_method", "parameters": "", "body": "self.solution = Solution()" }]
51+
},
52+
"_test_methods": {
53+
"list": [
54+
{
55+
"name": "test_is_same_tree",
56+
"signature": "(self, p_list: list[int | None], q_list: list[int | None], expected: bool)",
57+
"parametrize": "p_list, q_list, expected",
58+
"test_cases": "[([1, 2, 3], [1, 2, 3], True), ([1, 2], [1, None, 2], False), ([1, 2, 1], [1, 1, 2], False), ([], [], True), ([1], [1], True), ([1], [2], False), ([1, None, 2], [1, 2], False), ([1, 2, 3, 4, 5], [1, 2, 3, 4, 5], True), ([1, 2, 3, 4, 5], [1, 2, 3, 4, 6], False), ([1, 2, 3, None, 4], [1, 2, 3, None, 4], True), ([1, 2, 3, None, 4], [1, 2, 3, 4, None], False)]",
59+
"body": " result = run_is_same_tree(Solution, p_list, q_list)\n assert_is_same_tree(result, expected)"
60+
}
61+
]
62+
},
63+
"playground_imports": "from helpers import run_is_same_tree, assert_is_same_tree\nfrom solution import Solution\nfrom leetcode_py import TreeNode",
64+
"playground_setup": "# Example test case\np_list: list[int | None] = [1, 2, 3]\nq_list: list[int | None] = [1, 2, 3]\nexpected = True",
65+
"playground_run": "result = run_is_same_tree(Solution, p_list, q_list)\nresult",
66+
"playground_assert": "assert_is_same_tree(result, expected)"
67+
}

leetcode_py/cli/resources/leetcode/json/tags.json5

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@
110110

111111
// Blind 75 - (on-going)
112112
"blind-75": [
113+
"alien_dictionary",
113114
"best_time_to_buy_and_sell_stock",
114115
"binary_tree_level_order_traversal",
115116
"climbing_stairs",
@@ -149,6 +150,7 @@
149150
"remove_nth_node_from_end_of_list",
150151
"reverse_linked_list",
151152
"rotate_image",
153+
"same_tree",
152154
"search_in_rotated_sorted_array",
153155
"serialize_and_deserialize_binary_tree",
154156
"set_matrix_zeroes",
@@ -166,6 +168,7 @@
166168

167169
// NeetCode 150 - (on-going)
168170
"neetcode-150": [
171+
"alien_dictionary",
169172
"balanced_binary_tree",
170173
"best_time_to_buy_and_sell_stock",
171174
"binary_search",
@@ -181,6 +184,7 @@
181184
"course_schedule",
182185
"course_schedule_ii",
183186
"daily_temperatures",
187+
"decode_ways",
184188
"design_add_and_search_words_data_structure",
185189
"diameter_of_binary_tree",
186190
"evaluate_reverse_polish_notation",
@@ -192,6 +196,7 @@
192196
"implement_trie_prefix_tree",
193197
"insert_interval",
194198
"invert_binary_tree",
199+
"jump_game",
195200
"k_closest_points_to_origin",
196201
"kth_smallest_element_in_a_bst",
197202
"largest_rectangle_in_histogram",
@@ -218,9 +223,12 @@
218223
"product_of_array_except_self",
219224
"remove_nth_node_from_end_of_list",
220225
"reverse_linked_list",
226+
"rotate_image",
221227
"rotting_oranges",
228+
"same_tree",
222229
"search_in_rotated_sorted_array",
223230
"serialize_and_deserialize_binary_tree",
231+
"set_matrix_zeroes",
224232
"spiral_matrix",
225233
"subsets",
226234
"task_scheduler",
@@ -269,6 +277,7 @@
269277
"permutations",
270278
"product_of_array_except_self",
271279
"remove_nth_node_from_end_of_list",
280+
"rotate_image",
272281
"rotting_oranges",
273282
"search_in_rotated_sorted_array",
274283
"serialize_and_deserialize_binary_tree",

0 commit comments

Comments
 (0)