Skip to content

Commit dca2371

Browse files
committed
add subtree blog
1 parent cde0dd4 commit dca2371

1 file changed

Lines changed: 91 additions & 0 deletions

File tree

source/_posts/same-subtree.md

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
title: 判断一棵树是否是另一棵树的子树
2+
date: 2016-04-22 10:09:24
3+
tags: [算法, 积累, 搜索, 笔试]
4+
---
5+
昨天做到一道百度的笔试题,感觉对深搜的理解很有帮助,记录一下。
6+
7+
# 题目描述
8+
给定两个子树,树节点的数值唯一,问第二棵树是否是第一棵树的子树。是就返回1,否则-1。
9+
给定树节点的定义为:
10+
```
11+
struct tnode
12+
{
13+
int value;
14+
tnode* left;
15+
tnode* right;
16+
tnode(int v) { //这个构造函数是我为了调试时构造节点方便而写的
17+
value = v;
18+
left = NULL;
19+
right = NULL;
20+
}
21+
};
22+
```
23+
24+
# 考虑思路
25+
这题题意清晰,数据量没有给,应该也不是很大。有其他小伙伴认为可以遍历两个树,得到两个字符串,看是否第二个是第一个的子串。这个想法可能有一定的道理,但是同一个字符串,出现在遍历出来的字符串中的不同位置,也不一定代表就是子树,因为重复的字符串首先在第一个树中要是一个完整的子树才行。要进行这样的判断,太耗时耗力了,还不如考虑直接暴力搜索。
26+
27+
如果是暴搜的话,就要考虑如何搜。最直观的想法是,用第一层dfs枚举母树(第一棵树)的每个节点,然后用第二层dfs(或者bfs也行)遍历当前两棵子树,看是否一模一样。一旦发现相同的,就返回1。最后找不到,就返回-1。
28+
29+
然后就是一些细节问题了,要考虑左右子树完全相同才行。
30+
31+
# 关键代码
32+
```
33+
bool issame(tnode* mu_root, tnode* zi_root) { //判断两棵树是否相同
34+
if (mu_root->value != zi_root->value) //当前节点不同,树肯定不同
35+
return 0;
36+
if (mu_root->left==NULL && mu_root->right==NULL) { //当前节点相同且母树为叶节点
37+
if (zi_root->left==NULL && zi_root->right==NULL)//子树也是页节点
38+
return 1;
39+
return 0;
40+
}
41+
if (mu_root->left != NULL) {
42+
if (zi_root->left == NULL)
43+
return 0;
44+
bool bl = issame(mu_root->left, zi_root->left); //查看左子树
45+
if (!bl)
46+
return 0;
47+
}
48+
else if (zi_root->left != NULL) //母树没有左子树但子树有
49+
return 0;
50+
if (mu_root->right != NULL) {
51+
if (zi_root->right == NULL)
52+
return 0;
53+
bool bl = issame(mu_root->right, zi_root->right); //查看右子树
54+
if (!bl)
55+
return 0;
56+
}
57+
else if (zi_root->right != NULL) //母树没有右子树但子树有
58+
return 0;
59+
//左右子树都相同,才算相同
60+
return 1;
61+
}
62+
63+
bool dfs(tnode* mu_root, tnode* zi_root) { // 第一层dfs枚举
64+
if (mu_root->left==NULL && mu_root->right==NULL) { //若是叶子节点
65+
//直接返回是否同为叶节点且相等
66+
return mu_root->value==zi_root->value && zi_root->left==NULL && zi_root->right==NULL;
67+
}
68+
bool res = issame(mu_root, zi_root); //看以mu_root和zi_root为根节点的两个树是否相同
69+
if (res)
70+
return 1;
71+
//若不同,继续深搜枚举
72+
if (mu_root->left != NULL) { //左子节点
73+
bool res_l = dfs(mu_root->left, zi_root);
74+
if (res_l)
75+
return 1;
76+
}
77+
if (mu_root->right != NULL) { //右子节点
78+
bool res_r = dfs(mu_root->right, zi_root);
79+
if (res_r)
80+
return 1;
81+
}
82+
return 0;
83+
}
84+
85+
int solve(tnode* root1, tnode* root2) { //解决问题的主要函数
86+
bool ans = dfs(root1, root2);
87+
if (!ans)
88+
return -1;
89+
return ans;
90+
}
91+
```

0 commit comments

Comments
 (0)