Find Duplicate Subtrees 寻找重复的子树

给定一棵二叉树,返回所有重复的子树。对于同一类的重复子树,你只需要返回其中任意一棵的根结点即可。

两棵树重复是指它们具有相同的结构以及相同的结点值。

示例 1:

        1
       / \
      2   3
     /   / \
    4   2   4
       /
      4

下面是两个重复的子树:

      2
     /
    4

    4

因此,你需要以列表的形式返回上述重复子树的根结点。

思路:

我已开始的思路是采用后序遍历,每次遍历到一个节点就保存到一个map中

unordered_map<TreeNode*, int> m

保存的规则是如果对应的key相同(本意是key的val相同,但是map只能查找key相同的元素),就判断是否对应的节点的子树和root的子树是否相同,如果相同就把key对应的value+1,这样思考感觉是对的,其实是不对的!!!!因为如果map的key存的是TreeNode*,由于每一个TreeNode*分配都是在堆区,地址每个元素都是不一样的,遍历整棵树就不可能找到两个一模一样的key,虽然我们的本意是希望找到key对应的val相同的,于是修改代码,用两个map,一个是

unordered_map<TreeNode*, int> m

另一个是:

unordered_map<int,TreeNode*> va

通过va的key来保存TreeNode*对应的value,如果key相同则找到对应的value的TreeNode*,然后在加到m中。但是这样做也存在问题,如下图所示:

        1
       / \
      2   2
     /   / \
    3   4   2
           /
          4

va中先保存了key为2的红色的节点,当来到蓝色的节点2时,由于蓝色节点的子树和红色节点的子树不相同,于是不会加到m中,同样紫色的也不会计算到m中,所以这种解法只能保存第一次遇到的节点的值,以后再遇到只会和第一次保存的值比较,而不会出现第二次和第三次的比较,而结果很可能是第二次和第三次出现的相同。

这个就是博主的整道题思考过程,总之是希望找到一种结构,能够以当前节点的值来索引,不同节点如果相同值也能存储成不同的结构。所以直接参考了大神的discuss部分。

总的思路差不多,只不过用map来保存的结构变成了一棵树的前序遍历的序列化字符串比较,即:

unordered_map<string, int> m

key为当前节点的前序遍历的字符串序列化结果

value为对应序列出现的次数

在遍历过程中,如果value的值等于2,则把该节点的值加到res中,注意只加value==2的结果,避免重复添加。

代码如下:

string helper(TreeNode* root, unordered_map<string, int> &m, vector<TreeNode*> &res) {
	if (!root) {
		return "#";
	}
	string s = to_string(root->val) + "," + helper(root->left, m, res) + "," + helper(root->right, m, res);	
	m[s]++;
	if (m[s] == 2) {
		res.push_back(root);
	}
	return s;
}
vector<TreeNode*> findDuplicateSubtrees(TreeNode* root) {
	vector<TreeNode*> res;
	if (!root) {
		return res;
	}
	unordered_map<string, int> m;
	helper(root, m, res);
	return res;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值