leetcode每日一题【寻找重复的子树】2022/09/05

本文探讨了如何利用深度优先搜索和字符串哈希表解决LeetCode中的重复子树问题。作者首先介绍了两种思路:一是通过字符串形式的子树描述与哈希表计数,二是考虑左右子树结构的三元组表示法。代码实现和优化策略也进行了详细讲解。
摘要由CSDN通过智能技术生成

一、652. 寻找重复的子树【中】

1、题目:

给定一棵二叉树 root,返回所有重复的子树。

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

如果两棵树具有相同的结构和相同的结点值,则它们是重复的。

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/special-positions-in-a-binary-matrix

我的思路是深度优先,去用数组记录每个节点的左右子树。如下图,值为3的结点左子树为[4,2],右子树为[4]。这样很直观能看出哪些子树是相等的,但在程序上引来两个问题:

  • 数组个数会有多个,如何知道这些数组哪些是相等的?
  • 知道了相等的两个数组后,怎么知道这个数组是哪个节点的子树?
    在这里插入图片描述

2、思路一:深度优先+字符串哈希表

依然是深度优先,不同的是数组被替换成了字符串去描述一颗子树,再使用字符串哈希表,记录每种子树出现的次数,若在遍历过程中,子树字符串出现次数等于两次时,即记录该节点。
等于是因为,若多个子树是相同的,只需要返回一个子树的根即可。

代码(错误):

class Solution {
public:
    vector<TreeNode*> result; //结果节点
    vector<TreeNode*> findDuplicateSubtrees(TreeNode* root) {
        unordered_map<string,int> map; //记录子树出现次数的字符串哈希表
        dfs(root,map); 
        return result;
    }
    //dfs
    string dfs(TreeNode* node, unordered_map<string,int>& map){
        if(!node) return "";
        string left = dfs(node->left, map);
        string right = dfs(node->right, map);
        string current = left+to_string(node->val)+right;
        map[current] ++; // 记录该子树
        if(map[current]==2) result.push_back(node); // 出现次数为2次
        return current;
    }
};

在这里插入图片描述
思路没问题,但代码错了,该例子可视化后:
在这里插入图片描述
发现,子树也需要区分左右。那么在每次将左子树、右子树、节点连接成子树字符串返回上层时,左子树前加“(”,右子树前加“)”即可。
官解分析的时间复杂度:
在这里插入图片描述

代码:

//s:O(n) t:O(n)
class Solution {
public:
    vector<TreeNode*> result; //结果节点
    vector<TreeNode*> findDuplicateSubtrees(TreeNode* root) {
        unordered_map<string,int> map; //记录子树出现次数的字符串哈希表
        dfs(root,map); 
        return result;
    }
    //dfs
    string dfs(TreeNode* node, unordered_map<string,int>& map){
        if(!node) return "";
        string left = "("+dfs(node->left, map);
        string right = ")"+dfs(node->right, map);
        string current = left+to_string(node->val)+right;
        map[current] ++; // 记录该子树
        if(map[current]==2) result.push_back(node); // 出现次数为2次
        return current;
    }
};

3、思路二 :使用三元组进行唯一表示(待定)

例子:

代码:

//s:O() t:O()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值