给定两个非空二叉树 s 和 t,检验 s 中是否包含和 t 具有相同结构和节点值的子树。s 的一个子树包括 s 的一个节点和这个节点的所有子孙。s 也可以看做它自身的一棵子树。
示例 1:
给定的树 s:
3 / \ 4 5 / \ 1 2
给定的树 t:
4 / \ 1 2
返回 true,因为 t 与 s 的一个子树拥有相同的结构和节点值。
示例 2:
给定的树 s:
3 / \ 4 5 / \ 1 2 / 0
给定的树 t:
4 / \ 1 2
返回 false。
思路:
分两步走:1先找到大致相等节点,2再进行精确匹配
第一步大致相等节点的意思是先找到可能相等的节点,(比如通过前序遍历找到s->val和t->val相等的节点,或者是节点深度相同的节点),那么s节点就有可能和t节点完全一样。
第二部把找到的可能的s节点集合和t进行精确对比,返回结果。
我自己写了第一个方法,判断当前val和t的val是否相等,如果想等就放到map中,然后从map中逐个取出作精确对比。
代码如下:
bool sequealt(TreeNode* s, TreeNode* t) {
if ((!t && !s)) {
return true;
}
else if (t && s) {
return (t->val == s->val) && sequealt(t->left, s->left) && sequealt(t->right, s->right);
}
else {
return false;
}
}
void isSubtreeColle(TreeNode* s, TreeNode* t,bool &flag) {
if (flag || !s) {
return;
}
if (s->val == t->val) {
flag = sequealt(s, t);
if (flag) {
return;
}
}
isSubtreeColle(s->left, t,flag);
if (flag) {
return;
}
isSubtreeColle(s->right, t,flag);
}
bool isSubtree(TreeNode* s, TreeNode* t) {
if (!s) {
if (!t) {
return true;
}
return true;
}
if (s && !t) {
return true;
}
bool flag = false;
isSubtreeColle(s, t,flag);
return flag;
}
虽然ac了,但是耗时堪忧:
看看能不能优化,由于我们的第一步遍历了整个s,且限制条件只是值相等导致范围太大,于是map中有很多假阳性样例,而每次调用完全比对函数时,耗时都是O(n)(假设t有n个节点),所以我们应该尽量减少map中的假阳性样例,参考了discuss部分,有人用深度作为第一步限制条件,而时间效率有1/3的提升,所以我们把限制条件改为节点深度和t相等且val相等的才加入vector。于是有了方法2:
int getDepth(TreeNode* s,int d, vector<TreeNode*> &m,int t_root_value) {
if (!s) {
return -1;
}
int depth = max(getDepth(s->left, d,m,t_root_value), getDepth(s->right, d,m,t_root_value)) + 1;
if (depth == d && s->val==t_root_value) {
m.push_back(s);
}
return depth;
}
bool identical(TreeNode* s, TreeNode* t) {
if (!s && !t) {
return true;
}
if (s && t && s->val == t->val) {
return identical(s->left, t->left) && identical(s->right, t->right);
}
else {
return false;
}
}
bool isSubtree(TreeNode* s, TreeNode* t) {
if (!s && !t) {
return true;
}
if (!s || !t) {
return false;
}
vector<TreeNode*> m;
int t_root_value=t->val;
getDepth(s, getDepth(t, -1,m,t_root_value),m,t_root_value);
for (TreeNode* c : m) {
if (identical(c, t)) {
return true;
}
}
return false;
}
时间效率提升还是很明显的: