1,题目要求
判断一棵树是否是另一棵树的子树。
需要注意的是,这里的子树不是含有就是子树,要求原树中的子树部分不能有其他节点,就像example2中所说的那样。
2,题目思路
一开始,想象直接对s进行中序遍历,如果有节点的值和t的节点的值相同,就直接判断该s节点的左右节点的值是否和t左右节点的值相同。另外一种思路就是将s和t完全中序遍历并存储在向量中,然后做一个相同判断。
上述两种办法都不能不能解决example2中的问题,仅仅能判断t是否在s之中,因此都不可行。
参考了别人的代码,有以下方法:
核心还是递归的思想,新建一个子树是否相同的递归函数。然后在主函数体中进行递归的调用,依次对s中的每个节点与树t做相同判断。
3,程序源码
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
bool isSubtree(TreeNode* s, TreeNode* t) {
if(s == NULL) return false;
if(isSame(s,t)) return true;
return isSubtree(s->left, t) || isSubtree(s->right, t);
}
private:
bool isSame(TreeNode* s,TreeNode* t) //判断两棵树是否相同
{
if(s == NULL&& t == NULL)
return true;
if(s == NULL|| t == NULL)
return false;
if(s->val != t->val)
return false;
return isSame(s->left, t->left) && isSame(s->right, t->right);
}
};
这种方法还有一种改进的方式,即在对s的遍历是暴力的——要遍历s中的所有的节点。
优化的方式便是只对那些最大高度跟t相同的s节点进行比照。最大高度大于t的一定不可能是s的子树。
class Solution {
vector<TreeNode*> nodes;
public:
bool isSubtree(TreeNode* s, TreeNode* t) {
if (!s && !t) return true;
if (!s || !t) return false;
getDepth(s, getDepth(t, -1)); //将s中最大深度等于t的节点找出并按次序push
到nodes向量中
for (TreeNode* n: nodes)
if (identical(n, t))
return true;
return false;
}
int getDepth(TreeNode* r, int d) {
if (!r)
return -1;
int depth = max(getDepth(r->left, d), getDepth(r->right, d)) + 1;
// 对该节点所在的最大深度做判断
// -1只是为了找出t的最大高度,不需要讲其push到判断向量中
if (depth == d)
nodes.push_back(r);
return depth;
}
bool identical(TreeNode* a, TreeNode* b) {
if (!a && !b) return true;
if (!a || !b || a->val != b->val) return false;
return identical(a->left, b->left) && identical(a->right, b->right);
}
};