Subtree of Another Tree 另一个树的子树

给定两个非空二叉树 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;
   }

时间效率提升还是很明显的:




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值