本题源自leetcode 652
---------------------------------------------------------------------
思路1: 1 用一个map做映射。键是由节点的左子树根节点和右子树节点的值构成。值是一个vector
2 从根开始遍历。如果字数重复,则形成的字符串一样。
3 遍历map如果vector大于1 则说明有重复的子树。
代码:
vector<TreeNode*> findDuplicateSubtrees(TreeNode* root) {
map<string,vector<TreeNode*>> mp;
vector<TreeNode*> res;
if(!root)
return res;
backPath(root,mp);
for(auto it=mp.begin(); it != mp.end(); it++){
if(it->second.size() > 1)
res.push_back(it->second[0]);
}
return res;
}
string backPath(TreeNode* root,map<string,vector<TreeNode*>>& mp){
if(root == NULL)
return "";
string s = "(" + backPath(root->left,mp)+to_string(root->val)+backPath(root->right,mp)+")";
mp[s].push_back(root);
return s;
}
思路2: 1 把所有子树高度一样的节点存在一个vector中。然后遍历二维数组,把有相同高度的子树比较是否是重复子树
代码:
vector<TreeNode*> findDuplicateSubtrees(TreeNode* root) {
vector<TreeNode*> res;
if(!root)
return res;
vector<vector<TreeNode*>> height(1, vector<TreeNode*>());
findNode(height,root);
for(int i = 1; i < height.size(); i++){
for(int j = 0; j < height[i].size(); j++){
if(height[i][j] == NULL)
continue;
bool exist = false;
for(int k = j + 1; k < height[i].size(); k++){
if(isSameTree(height[i][j], height[i][k])){
height[i][k] = NULL;
exist = true;
}
}
if(exist)
res.push_back(height[i][j]);
}
}
return res;
}
int findNode(vector<vector<TreeNode*>>& height,TreeNode* root){
if(!root)
return 0;
int left = findNode(height,root->left);
int right = findNode(height,root->right);
int h = max(left,right)+1;
if(h == height.size())
height.push_back({root});
else
height[h].push_back(root);
return h;
}
bool isSameTree(TreeNode* p,TreeNode* q){
if(!p && !q)
return true;
if(p==NULL || q==NULL)
return false;
if(p->val != q->val)
return false;
return isSameTree(p->left,q->left) && isSameTree(p->right,q->right);
}