• 652. 寻找重复的子树


    652. 寻找重复的子树

    难度中等545收藏分享切换为英文接收动态反馈

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

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

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

    示例 1:

    输入:root = [1,2,3,4,null,2,4,null,null,4]
    输出:[[2,4],[4]]

    示例 2:

    输入:root = [2,1,1]
    输出:[[1]]

    示例 3:

    输入:root = [2,2,2,3,null,3,null]
    输出:[[2,3],[3]]
    

    提示:

    • 树中的结点数在[1,10^4]范围内。
    • -200 <= Node.val <= 200

    分析:胡汉三又回来写题了,好久不写题了变得好垃圾了QAQ,疯狂看题解。本题的题意就是输出所有重复子树的根节点,需要注意的是,对于一组重复的子树,输出其中任意一个根即可。

    1.想判断两棵树相等,需要把两颗树都遍历一遍,然后看是否相同,后续还要进行去重。。。个屁啊,没事找事,是个思路但是妥妥不对劲 

    2.针对看一下上述的优化点 ,实际上我们看完整棵树就理应知道所有的子结构了,另外判断结构相似可以比较两个结构的序列化结果;还没完,本题中强调了子树,子树的叶子在原树上也必须是叶子,而且我们很容易发现递归性质--要想判断大一点的结构是否相同,就要先看小一点的结构是否相同,而DFS的返回顺序正好就符合了这一条性质;现在我们来看看怎么去快速查找树中的相似子树结构,实际上上面也提到了,树的结构可以用序列化结果表示,那么我们只需要获取所有的子树,再使用他们的序列化结果进行查询即可。

    1. /**
    2. * Definition for a binary tree node.
    3. * struct TreeNode {
    4. * int val;
    5. * TreeNode *left;
    6. * TreeNode *right;
    7. * TreeNode() : val(0), left(nullptr), right(nullptr) {}
    8. * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
    9. * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
    10. * };
    11. */
    12. class Solution {
    13. public:
    14. unordered_mapint> repeat_tree;
    15. string dfs(TreeNode* root, vector &nodes){
    16. if(!root){
    17. return "";
    18. }
    19. string tree_serial = to_string(root -> val) + "(" + dfs(root -> left, nodes) + ")" + "(" + dfs(root -> right, nodes) + ")";
    20. if(repeat_tree.find(tree_serial) == repeat_tree.end()){
    21. repeat_tree[tree_serial] = 1;
    22. } else {
    23. ++ repeat_tree[tree_serial];
    24. if(repeat_tree[tree_serial] == 2){
    25. nodes.emplace(nodes.end(), root);
    26. }
    27. }
    28. return tree_serial;
    29. }
    30. vector findDuplicateSubtrees(TreeNode* root) {
    31. vector nodes;
    32. dfs(root, nodes);
    33. return nodes;
    34. }
    35. };

    3.官网解法:用int序号替代string加速相等的判断

    1. class Solution {
    2. public:
    3. vector findDuplicateSubtrees(TreeNode* root) {
    4. dfs(root);
    5. return {repeat.begin(), repeat.end()};
    6. }
    7. int dfs(TreeNode* node) {
    8. if (!node) {
    9. return 0;
    10. }
    11. auto tri = tuple{node->val, dfs(node->left), dfs(node->right)};
    12. if (auto it = seen.find(tri); it != seen.end()) {//当前结构出现过
    13. repeat.insert(it->second.first);//repeat 表示出现的重复串 插入根节点
    14. return it->second.second;//返回代表当前串的序号 用序号替代string加速匹配
    15. }
    16. else {//当前结构没出现过,加入seen集合
    17. seen[tri] = {node, ++idx};
    18. return idx;
    19. }
    20. }
    21. private:
    22. static constexpr auto tri_hash = [fn = hash<int>()](const tuple<int, int, int>& o) -> size_t {
    23. auto&& [x, y, z] = o;
    24. return (fn(x) << 24) ^ (fn(y) << 8) ^ fn(z);
    25. };
    26. unordered_mapint, int, int>, pairint>, decltype(tri_hash)> seen{0, tri_hash};
    27. unordered_set repeat;
    28. int idx = 0;
    29. };

  • 相关阅读:
    【Element-UI】实现动态树、数据表格及分页效果
    Python内置函数系统学习(2)——数据转换与计算 (详细语法参考+参数说明+应用场景示例), max()在列表、元组、字典中的综合应用 | 编程实现当前内存使用情况的监控
    特殊类设计[下] --- 单例模式
    牛客小白月赛79
    Java 线程池异步任务
    Redis快速上手篇五(持久化)
    git笔记
    【车间调度】基于模拟退火优化算法的的并行车间机器优化调度(Matlab代码实现)
    【ASM】字节码操作 Label 如何使用 生成 if 语句
    打通Web安全思路:为什么我们需要同源策略?
  • 原文地址:https://blog.csdn.net/qq_39304630/article/details/126704260