572. 另一棵树的子树

给你两棵二叉树 root 和 subRoot 。检验 root 中是否包含和 subRoot 具有相同结构和节点值的子树。如果存在,返回 true ;否则,返回 false 。

二叉树 tree 的一棵子树包括 tree 的某个节点和这个节点的所有后代节点。tree 也可以看做它自身的一棵子树。

示例 1:

输入:root = [3,4,5,1,2], subRoot = [4,1,2]
输出:true

示例 2:

输入:root = [3,4,5,1,2,null,null,null,null,0], subRoot = [4,1,2]
输出:false

提示:

  • root 树上的节点数量范围是 [1, 2000]
  • subRoot 树上的节点数量范围是 [1, 1000]
  • -104 <= root.val <= 104
  • -104 <= subRoot.val <= 104

第一种方法:先深度优先 || 先序遍历主树,直到找到和 subRoot 相同值的节点,再以此为起点与 subRoot 做比较。属于暴力深搜的一种。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
func isSubtree(s *TreeNode, t *TreeNode) bool { 
if s == nil {
return false
}
return check(s, t) || isSubtree(s.Left, t) || isSubtree(s.Right, t)
}

func check(a, b *TreeNode) bool {
if a == nil && b == nil {
return true
}
if a == nil || b == nil {
return false
}

if a.Val == b.Val {
return check(a.Left, b.Left) && check(a.Right, b.Right)
}
return false
}

第二种方法:利用树的性质,将空子树补全,这样能得到唯一的一个先序遍历结果,然后判断 subRoot 的遍历结果是否是 root 遍历结果的子串,即可确认是否是题目要求的子树。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
func isSubtree(s *TreeNode, t *TreeNode) bool { 
maxEle := math.MinInt32
getMaxElement(s, &maxEle)
getMaxElement(t, &maxEle)
lNull := maxEle + 1
rNull := maxEle + 2
sl, tl := getDfsOrder(s, []int{}, lNull, rNull), getDfsOrder(t, []int{}, lNull, rNull)
return kmp(sl, tl)
}

func kmp(s, t []int) bool {
sLen, tLen := len(s), len(t)
fail := make([]int, sLen)

for i := 0; i < sLen; i++ {
fail[i] = -1
}
for i, j := 1, -1; i < tLen; i++ {
for j != -1 && t[i] != t[j+1] {
j = fail[j]
}
if t[i] == t[j+1] {
j++
}
fail[i] = j
}
for i, j := 0, -1; i < sLen; i++ {
for j != -1 && s[i] != t[j+1] {
j = fail[j]
}
if s[i] == t[j+1] {
j++
}
if j == tLen - 1 {
return true
}
}
return false
}

func getDfsOrder(t *TreeNode, list []int, lNull, rNull int) []int {
if t == nil {
return list
}
list = append(list, t.Val)
if t.Left != nil {
list = getDfsOrder(t.Left, list, lNull, rNull)
} else {
list = append(list, lNull)
}

if t.Right != nil {
list = getDfsOrder(t.Right, list, lNull, rNull)
} else {
list = append(list, rNull)
}
return list
}

func getMaxElement(t *TreeNode, maxEle *int) {
if t == nil {
return
}
if t.Val > *maxEle {
*maxEle = t.Val
}
getMaxElement(t.Left, maxEle)
getMaxElement(t.Right, maxEle)
}