Skip to content

Commit 90af76f

Browse files
committed
feat: solve #229 with python
1 parent c2a2065 commit 90af76f

File tree

1 file changed

+116
-0
lines changed

1 file changed

+116
-0
lines changed

subtree-of-another-tree/EGON.py

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
from typing import Optional
2+
from unittest import TestCase, main
3+
4+
5+
# Definition for a binary tree node.
6+
class TreeNode:
7+
def __init__(self, val=0, left=None, right=None):
8+
self.val = val
9+
self.left = left
10+
self.right = right
11+
12+
13+
class Solution:
14+
def isSubtree(self, root: Optional[TreeNode], subRoot: Optional[TreeNode]) -> bool:
15+
return self.solve_dfs(root, subRoot)
16+
17+
"""
18+
Runtime: 35 ms (Beats 90.24%)
19+
Time Complexity: O(n)
20+
- root 트리의 크기를 n이라 하면, root 트리의 모든 노드를 조회하는데 O(n)
21+
- 각 노드마다 is_same_tree 실행하는데, subRoot 트리의 크기를 m이라 하면, 최대 subRoot의 노드의 크기만큼 조회하므로 * O(m)
22+
> O(n) * O(m) ~= O(n * m)
23+
24+
Memory: 17.09 (Beats 9.93%)
25+
Space Complexity: O(max(n, m))
26+
- stack의 최대 크기는 root 트리가 편향된 경우이며, 이는 root 트리의 노드의 총 갯수와 같으므로 O(n), upper bound
27+
- is_same_tree 함수의 재귀 스택의 최대 깊이는 subRoot 트리가 편향된 경우이며, 이는 subRoot 트리의 노드의 총 갯수와 같으므로 O(m), upper bound
28+
> O(n) + O(m) ~= O(max(n, m))
29+
"""
30+
def solve_dfs(self, root: Optional[TreeNode], subRoot: Optional[TreeNode]) -> bool:
31+
32+
def is_same_tree(p: Optional[TreeNode], q: Optional[TreeNode]) -> bool:
33+
if p is None and q is None:
34+
return True
35+
elif (p is not None and q is not None) and (p.val == q.val):
36+
return is_same_tree(p.left, q.left) and is_same_tree(p.right, q.right)
37+
else:
38+
return False
39+
40+
result = False
41+
stack = [root]
42+
while stack:
43+
curr = stack.pop()
44+
if (curr and subRoot) and curr.val == subRoot.val:
45+
result = result or is_same_tree(curr, subRoot)
46+
47+
if curr.left:
48+
stack.append(curr.left)
49+
50+
if curr.right:
51+
stack.append(curr.right)
52+
53+
return result
54+
55+
56+
class _LeetCodeTestCases(TestCase):
57+
def test_1(self):
58+
root = TreeNode(3)
59+
root_1 = TreeNode(4)
60+
root_2 = TreeNode(5)
61+
root.left = root_1
62+
root.right = root_2
63+
root_3 = TreeNode(1)
64+
root_4 = TreeNode(2)
65+
root.left.left = root_3
66+
root.left.right = root_4
67+
68+
subRoot = TreeNode(4)
69+
sub_1 = TreeNode(1)
70+
sub_2 = TreeNode(2)
71+
subRoot.left = sub_1
72+
subRoot.right = sub_2
73+
74+
output = True
75+
self.assertEqual(Solution.isSubtree(Solution(), root, subRoot), output)
76+
77+
def test_2(self):
78+
root = TreeNode(3)
79+
root_1 = TreeNode(4)
80+
root_2 = TreeNode(5)
81+
root.left = root_1
82+
root.right = root_2
83+
root_3 = TreeNode(1)
84+
root_4 = TreeNode(2)
85+
root.left.left = root_3
86+
root.left.right = root_4
87+
root_5 = TreeNode(0)
88+
root_4.left = root_5
89+
90+
subRoot = TreeNode(4)
91+
sub_1 = TreeNode(1)
92+
sub_2 = TreeNode(2)
93+
subRoot.left = sub_1
94+
subRoot.right = sub_2
95+
96+
output = False
97+
self.assertEqual(Solution.isSubtree(Solution(), root, subRoot), output)
98+
99+
def test_3(self):
100+
root = TreeNode(1)
101+
root.right = TreeNode(1)
102+
root.right.right = TreeNode(1)
103+
root.right.right.right = TreeNode(1)
104+
root.right.right.right.right = TreeNode(1)
105+
root.right.right.right.right.right = TreeNode(2)
106+
107+
subRoot = TreeNode(1)
108+
subRoot.right = TreeNode(1)
109+
subRoot.right.right = TreeNode(2)
110+
111+
output = True
112+
self.assertEqual(Solution.isSubtree(Solution(), root, subRoot), output)
113+
114+
115+
if __name__ == '__main__':
116+
main()

0 commit comments

Comments
 (0)