-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathC03_IsSubtree.java
146 lines (134 loc) · 4.84 KB
/
C03_IsSubtree.java
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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
package C16_KMP;
import C01_random.GenerateRandomBT;
import C01_random.GenerateRandomBT.TreeNode;
import java.util.ArrayList;
public class C03_IsSubtree {
public static boolean isSubtree(TreeNode tree, TreeNode subtree) {
if (subtree == null) { // 空树必定是子树
return true;
}
if (tree == null) {
return false;
}
return indexOf(preSerialize(tree), preSerialize(subtree)) != -1;
}
// 先序序列化
private static ArrayList<Integer> preSerialize(TreeNode head) {
ArrayList<Integer> list = new ArrayList<Integer>();
preS(head, list);
return list;
}
private static void preS(TreeNode head, ArrayList<Integer> list) {
if (head == null) {
list.add(null);
return;
}
list.add(head.value);
preS(head.left, list);
preS(head.right, list);
}
// KMP,时间复杂度O(N)
private static int indexOf(ArrayList<Integer> list, ArrayList<Integer> match) {
if (list == null || match == null || list.size() < 1 || list.size() < match.size()) {
return -1;
}
int listSize = list.size();
int matchSize = match.size();
int[] preNext = generatePreNextArray(match);
int lIndex = 0;
int mIndex = 0;
while (lIndex < listSize && mIndex < matchSize) {
if (isEqual(list.get(lIndex), match.get(mIndex))) {
lIndex++;
mIndex++;
} else if (preNext[mIndex] > -1) {
mIndex = preNext[mIndex];
} else {
lIndex++;
}
}
return mIndex == matchSize ? lIndex - mIndex : -1;
}
private static int[] generatePreNextArray(ArrayList<Integer> list) {
int listSize = list.size();
if (listSize == 1) {
return new int[] {-1};
}
int[] preNext = new int[listSize];
preNext[0] = -1;
preNext[1] = 0;
int matchIndex = 0;
int i = 2;
while (i < listSize) {
if (isEqual(list.get(i - 1), list.get(matchIndex))) {
preNext[i++] = ++matchIndex;
} else if (matchIndex > 0) {
matchIndex = preNext[matchIndex];
} else {
preNext[i++] = 0;
}
}
return preNext;
}
private static boolean isEqual(Integer o1, Integer o2) {
if (o1 == null && o2 == null)
return true;
if (o1 == null || o2 == null)
return false;
return o1.equals(o2);
}
// 暴力递归
public static boolean isSubtree2(TreeNode tree, TreeNode subtree) {
if (subtree == null) { // 空树必定是子树
return true;
}
if (tree == null) {
return false;
}
// 两棵树是否完全相同
if (isSameTree(tree, subtree)) {
return true;
}
// 左树或者右树是否与subtree相同
return isSubtree2(tree.left, subtree) ||
isSubtree2(tree.right, subtree);
}
private static boolean isSameTree(TreeNode head1, TreeNode head2) {
if (head1 == null && head2 == null) { // 两树都为空,则相等
return true;
}
if (head1 == null || head2 == null) { // 有一颗树为空,则不相等
return false;
}
// 比较两棵树的头节点值、左节点值、右节点值
return head1.value == head2.value &&
isSameTree(head1.left, head2.left) &&
isSameTree(head1.right, head2.right);
}
public static void main(String[] args) {
TreeNode tree = new TreeNode(0);
tree.left = new TreeNode(1);
TreeNode subtree = new TreeNode(1);
System.out.printf("ans1=%b, ans2=%b\n", isSubtree(tree, subtree), isSubtree2(tree, subtree));
tree.right = new TreeNode(1);
subtree.right = new TreeNode(1);
System.out.printf("ans1=%b, ans2=%b\n", isSubtree(tree, subtree), isSubtree2(tree, subtree));
System.out.println("======================================");
int testTimes = 1000000;
int treeMaxHeight = 8;//3;
int subtreeMaxHeight = 4;//2;
int maxValue = 5;
for (int i = 0; i < testTimes; i++) {
tree = GenerateRandomBT.generateRandomBT(treeMaxHeight, maxValue);
subtree = GenerateRandomBT.generateRandomBT(subtreeMaxHeight, maxValue);
boolean ans1 = isSubtree(tree, subtree);
boolean ans2 = isSubtree2(tree, subtree);
if (ans1 != ans2) {
System.out.printf("Oops! i=%d\n", i);
System.out.printf("ans1=%b, ans2=%b\n", ans1, ans2);
GenerateRandomBT.printTree(tree);
GenerateRandomBT.printTree(subtree);
}
}
}
}