问题描述:
给定一棵二叉树,返回所有重复的子树。对于同一类的重复子树,你只需要返回其中任意一棵的根结点即可。
两棵树重复是指它们具有相同的结构以及相同的结点值。
示例 1:
1 / \ 2 3 / / \ 4 2 4 / 4
下面是两个重复的子树:
2 / 4
和
4
因此,你需要以列表的形式返回上述重复子树的根结点。
基本思路:
还是利用哈希映射进行分类的思想来解这道题。问题的关键就是怎么确定分组。
大家都知道一个节点就可以代表一棵树,然而这种方法过于繁琐,原因是我们不得不通过遍历才能确定这他所代表的树。
这里我们采用二叉树的序列化的算法——把一棵二叉树表示为带空节点的前序遍历的字符串。
然后把这个作为关键字统计具有相同字符串的节点的个数。
AC代码:
/**
* 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 {
private:
vector<TreeNode *>res;
unordered_map<string, int> hashmap;
public:
string Serialize(TreeNode *root) {
// 由于序列化的二叉树通过一个字符串就可以表示一棵树的完整信息
// 所以我们这里才会选择序列化二叉树
// 不然直接使用节点,我们还有对节点代表的树进行遍历,很麻烦
if (!root) return "#";
string temp = to_string(root->val) + "," + Serialize(root->left) + ","
+ Serialize(root->right);
++hashmap[temp];
if (hashmap[temp] == 2) {
res.push_back(root);
}
return temp;
}
vector<TreeNode*> findDuplicateSubtrees(TreeNode* root) {
// 说明递归的空间浪费真的不容忽视
// 与其多次递归,不如合并递归
Serialize(root);
return res;
}
};
其它经验:
我跟人在做这道题的时候出现了MLE,这种情况真是难搞。
因为如果时TLE的话我还能改进算法,MLE我还真的不知道从何下手。
后面解决的办法就是通过合并递归的方式。
把节点序列化和将节点添加到hashmap中合为一体。
这样我们就不会堆栈溢出了。
总结就是递归会call stack overflow, 为了防止MLE,合并递归。