最小高度树

这个题需要复杂的证明,这里不再用数学证明。

  • 最小高度树的高度公式

    • 设树中距离最远的两个节点为 x, y它们之间的距离为 maxdist = dist[x][y]

    • 则任意最小高度树的高度为

      minheight=⌈maxdist/2⌉

    • 换句话说,最小高度树的高度是最长路径长度的一半向上取整。

  • 最小高度树的根节点位置

    • 根节点一定在这条最长路径上。

    • 如果根不在最长路径上,则无论怎么选,高度都不可能小于 minheight,会和最长路径长度矛盾。

只是说一说直觉就可以理解的。

  • 想象最长路径是一条线,根放在中间,两边叶子到根的距离最均衡,形成最小高度。

  • 如果根偏离这条路径,则最长的一边会更长,高度反而变大。

  • 树的高度取决于最远的叶子对

  • 把根放在最远叶子对的中间,让两边尽量平衡。

  • 就像把跷跷板的支点放在中间,重量(距离)最均衡,高度最小。

因此我们只需要求出路径最长的两个叶子节点即可,并求出其路径的最中间的节点即为最小高度树的根节点。可以利用以下算法找到图中距离最远的两个节点与它们之间的路径:

以任意节点 p 出现,利用广度优先搜索或者深度优先搜索找到以 p 为起点的最长路径的终点 x(树没有环,所以从任意节点出发,沿着最长的分支走,最远的点一定落在最长路径的某个端点上。);以节点 x 出发,找到以 x 为起点的最长路径的终点 y;x 到 y 之间的路径即为图中的最长路径,找到路径的中间节点即为根节点。
有了以上前置知识,我们使用拓扑排序的方法进行求解,不再使用深度搜素和广度搜索的方法:

cpp 复制代码
class Solution {
public:
    vector<int> findMinHeightTrees(int n, vector<vector<int>>& edges) {
        if(n==1) return {0};

        //创建邻接矩阵
        vector<unordered_set<int>> graphs(n);
        for(auto& e:edges){
            graphs[e[0]].insert(e[1]);
            graphs[e[1]].insert(e[0]);
        }


        vector<int> leves;
        //找叶子节点
        for(int i =0;i<n;i++){
            if(graphs[i].size()==1) leves.push_back(i); 
        }

        // 删结点
        int remaining=n;
        while(remaining>2){
            remaining-=leves.size();
            vector<int> newleves;
            //删边
            for(auto e:leves){
                int ajx=*(graphs[e].begin());
                graphs[ajx].erase(e);
                if(graphs[ajx].size()==1) newleves.push_back(ajx);
            }
            leves=newleves;
        }

        return leves;
    }
};

思路总结

  1. 树的最小高度树的根一定在最长路径的中间 → 对应最终剩下 1 或 2 个节点

  2. 剥叶子法

    • 反复删除所有叶子节点(度 = 1)

    • 剩下的节点就是最小高度树的根

  3. 时间复杂度 O(n),空间复杂度 O(n)。

相关推荐
仰泳的熊猫2 小时前
题目2570:蓝桥杯2020年第十一届省赛真题-成绩分析
数据结构·c++·算法·蓝桥杯
无极低码5 小时前
ecGlypher新手安装分步指南(标准化流程)
人工智能·算法·自然语言处理·大模型·rag
软件算法开发6 小时前
基于海象优化算法的LSTM网络模型(WOA-LSTM)的一维时间序列预测matlab仿真
算法·matlab·lstm·一维时间序列预测·woa-lstm·海象优化
superior tigre6 小时前
22 括号生成
算法·深度优先
努力也学不会java7 小时前
【缓存算法】一篇文章带你彻底搞懂面试高频题LRU/LFU
java·数据结构·人工智能·算法·缓存·面试
旖-旎8 小时前
二分查找(x的平方根)(4)
c++·算法·二分查找·力扣·双指针
ECT-OS-JiuHuaShan8 小时前
朱梁万有递归元定理,重构《易经》
算法·重构
智者知已应修善业8 小时前
【51单片机独立按键控制数码管移动反向,2片74CH573/74CH273段和位,按键按下保持原状态】2023-3-25
经验分享·笔记·单片机·嵌入式硬件·算法·51单片机
khddvbe9 小时前
C++并发编程中的死锁避免
开发语言·c++·算法