Skip to content

Commit 6917bf7

Browse files
committed
Subtree of another tree
1 parent 087d2b3 commit 6917bf7

File tree

2 files changed

+274
-0
lines changed

2 files changed

+274
-0
lines changed
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
//572. Subtree of another tree
2+
// Topics: 'Tree', 'Binary Tree', 'Depth-First Search', 'String Matching', 'Hash Function'
3+
4+
// Given the roots of two binary trees root and subRoot, return true if there is a subtree of root with the same structure and node values of subRoot and false otherwise.
5+
6+
// A subtree of a binary tree tree is a tree that consists of a node in tree and all of this node's descendants. The tree tree could also be considered as a subtree of itself.
7+
8+
// Example 1:
9+
10+
// Input: root = [3,4,5,1,2], subRoot = [4,1,2]
11+
// Output: true
12+
13+
// Example 2:
14+
15+
// Input: root = [3,4,5,1,2,null,null,null,null,0], subRoot = [4,1,2]
16+
// Output: false
17+
18+
// Constraints:
19+
20+
// The number of nodes in the root tree is in the range [1, 2000].
21+
// The number of nodes in the subRoot tree is in the range [1, 1000].
22+
// -104 <= root.val <= 104
23+
// -104 <= subRoot.val <= 104
24+
25+
package subtreeofanothertree
26+
27+
func isSubtree(root *TreeNode, subRoot *TreeNode) bool {
28+
if root == nil {
29+
return false
30+
}
31+
if root.Val == subRoot.Val && equal(root, subRoot) {
32+
return true
33+
}
34+
return isSubtree(root.Left, subRoot) || isSubtree(root.Right, subRoot)
35+
}
36+
37+
func equal(subRoot0, subRoot *TreeNode) bool {
38+
if subRoot0 == nil && subRoot == nil {
39+
return true
40+
}
41+
if subRoot0 == nil || subRoot == nil {
42+
return false
43+
}
44+
if subRoot0.Val != subRoot.Val {
45+
return false
46+
}
47+
return equal(subRoot0.Left, subRoot.Left) && equal(subRoot0.Right, subRoot.Right)
48+
}
49+
50+
type TreeNode struct {
51+
Val int
52+
Right *TreeNode
53+
Left *TreeNode
54+
}
Lines changed: 220 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,220 @@
1+
package subtreeofanothertree
2+
3+
import "testing"
4+
5+
func TestIsSubtree(t *testing.T) {
6+
tests := []struct {
7+
name string
8+
root *TreeNode
9+
subRoot *TreeNode
10+
want bool
11+
}{
12+
{
13+
name: "example 1 - subtree exists",
14+
root: &TreeNode{
15+
Val: 3,
16+
Left: &TreeNode{
17+
Val: 4,
18+
Left: &TreeNode{Val: 1},
19+
Right: &TreeNode{Val: 2},
20+
},
21+
Right: &TreeNode{Val: 5},
22+
},
23+
subRoot: &TreeNode{
24+
Val: 4,
25+
Left: &TreeNode{Val: 1},
26+
Right: &TreeNode{Val: 2},
27+
},
28+
want: true,
29+
},
30+
{
31+
name: "example 2 - subtree does not exist",
32+
root: &TreeNode{
33+
Val: 3,
34+
Left: &TreeNode{
35+
Val: 4,
36+
Left: &TreeNode{
37+
Val: 1,
38+
Left: &TreeNode{Val: 0},
39+
},
40+
Right: &TreeNode{Val: 2},
41+
},
42+
Right: &TreeNode{Val: 5},
43+
},
44+
subRoot: &TreeNode{
45+
Val: 4,
46+
Left: &TreeNode{Val: 1},
47+
Right: &TreeNode{Val: 2},
48+
},
49+
want: false,
50+
},
51+
{
52+
name: "root and subRoot are identical",
53+
root: &TreeNode{
54+
Val: 1,
55+
Left: &TreeNode{Val: 2},
56+
Right: &TreeNode{Val: 3},
57+
},
58+
subRoot: &TreeNode{
59+
Val: 1,
60+
Left: &TreeNode{Val: 2},
61+
Right: &TreeNode{Val: 3},
62+
},
63+
want: true,
64+
},
65+
{
66+
name: "single node match",
67+
root: &TreeNode{Val: 1},
68+
subRoot: &TreeNode{Val: 1},
69+
want: true,
70+
},
71+
{
72+
name: "single node no match",
73+
root: &TreeNode{Val: 1},
74+
subRoot: &TreeNode{Val: 2},
75+
want: false,
76+
},
77+
{
78+
name: "subRoot is a leaf in root",
79+
root: &TreeNode{
80+
Val: 1,
81+
Left: &TreeNode{
82+
Val: 2,
83+
Left: &TreeNode{Val: 4},
84+
},
85+
Right: &TreeNode{Val: 3},
86+
},
87+
subRoot: &TreeNode{Val: 4},
88+
want: true,
89+
},
90+
{
91+
name: "partial match - different structure",
92+
root: &TreeNode{
93+
Val: 1,
94+
Left: &TreeNode{
95+
Val: 2,
96+
Right: &TreeNode{Val: 3},
97+
},
98+
},
99+
subRoot: &TreeNode{
100+
Val: 2,
101+
Left: &TreeNode{Val: 3},
102+
},
103+
want: false,
104+
},
105+
{
106+
name: "subRoot larger than any subtree",
107+
root: &TreeNode{
108+
Val: 1,
109+
Left: &TreeNode{Val: 2},
110+
Right: &TreeNode{Val: 3},
111+
},
112+
subRoot: &TreeNode{
113+
Val: 1,
114+
Left: &TreeNode{
115+
Val: 2,
116+
Left: &TreeNode{Val: 4},
117+
},
118+
Right: &TreeNode{Val: 3},
119+
},
120+
want: false,
121+
},
122+
{
123+
name: "multiple nodes with same value",
124+
root: &TreeNode{
125+
Val: 1,
126+
Left: &TreeNode{
127+
Val: 2,
128+
Left: &TreeNode{Val: 4},
129+
},
130+
Right: &TreeNode{
131+
Val: 2,
132+
Left: &TreeNode{Val: 4},
133+
Right: &TreeNode{Val: 5},
134+
},
135+
},
136+
subRoot: &TreeNode{
137+
Val: 2,
138+
Left: &TreeNode{Val: 4},
139+
},
140+
want: true,
141+
},
142+
{
143+
name: "deep tree with subtree at bottom",
144+
root: &TreeNode{
145+
Val: 10,
146+
Left: &TreeNode{
147+
Val: 5,
148+
Left: &TreeNode{
149+
Val: 3,
150+
Left: &TreeNode{Val: 1},
151+
Right: &TreeNode{Val: 4},
152+
},
153+
},
154+
},
155+
subRoot: &TreeNode{
156+
Val: 3,
157+
Left: &TreeNode{Val: 1},
158+
Right: &TreeNode{Val: 4},
159+
},
160+
want: true,
161+
},
162+
{
163+
name: "same values but different structure",
164+
root: &TreeNode{
165+
Val: 1,
166+
Left: &TreeNode{Val: 2},
167+
},
168+
subRoot: &TreeNode{
169+
Val: 1,
170+
Right: &TreeNode{Val: 2},
171+
},
172+
want: false,
173+
},
174+
{
175+
name: "negative values",
176+
root: &TreeNode{
177+
Val: -10,
178+
Left: &TreeNode{Val: -20},
179+
Right: &TreeNode{Val: -5},
180+
},
181+
subRoot: &TreeNode{
182+
Val: -20,
183+
},
184+
want: true,
185+
},
186+
{
187+
name: "complex tree with no match",
188+
root: &TreeNode{
189+
Val: 12,
190+
Left: &TreeNode{
191+
Val: 7,
192+
Left: &TreeNode{Val: 3},
193+
Right: &TreeNode{Val: 9},
194+
},
195+
Right: &TreeNode{
196+
Val: 15,
197+
Right: &TreeNode{Val: 20},
198+
},
199+
},
200+
subRoot: &TreeNode{
201+
Val: 7,
202+
Left: &TreeNode{Val: 3},
203+
Right: &TreeNode{
204+
Val: 9,
205+
Left: &TreeNode{Val: 8},
206+
},
207+
},
208+
want: false,
209+
},
210+
}
211+
212+
for _, tt := range tests {
213+
t.Run(tt.name, func(t *testing.T) {
214+
got := isSubtree(tt.root, tt.subRoot)
215+
if got != tt.want {
216+
t.Errorf("isSubtree() = %v, want %v", got, tt.want)
217+
}
218+
})
219+
}
220+
}

0 commit comments

Comments
 (0)