leetcode0310. 最小高度树-medium

1 题目:最小高度树

官方标定难度:中

树是一个无向图,其中任何两个顶点只通过一条路径连接。 换句话说,任何一个没有简单环路的连通图都是一棵树。

给你一棵包含 n 个节点的树,标记为 0 到 n - 1 。给定数字 n 和一个有 n - 1 条无向边的 edges 列表(每一个边都是一对标签),其中 edges[i] = [ai, bi] 表示树中节点 ai 和 bi 之间存在一条无向边。

可选择树中任何一个节点作为根。当选择节点 x 作为根节点时,设结果树的高度为 h 。在所有可能的树中,具有最小高度的树(即,min(h))被称为 最小高度树 。

请你找到所有的 最小高度树 并按 任意顺序 返回它们的根节点标签列表。

树的 高度 是指根节点和叶子节点之间最长向下路径上边的数量。

示例 1:

输入:n = 4, edges = [[1,0],[1,2],[1,3]]

输出:[1]

解释:如图所示,当根是标签为 1 的节点时,树的高度是 1 ,这是唯一的最小高度树。

示例 2:

输入:n = 6, edges = [[3,0],[3,1],[3,2],[3,4],[5,4]]

输出:[3,4]

提示:

1 < = n < = 2 ∗ 1 0 4 1 <= n <= 2 * 10^4 1<=n<=2∗104

edges.length == n - 1

0 <= ai, bi < n

ai != bi

所有 (ai, bi) 互不相同

给定的输入 保证 是一棵树,并且 不会有重复的边

2 solution

先随便找一个顶点作为根节点,dfs 获取每个节点 u 的最大高度 f[u], 和次大高度 g[u] 然后,再遍历一次获取,反向的最大高度 h[u] ,即从父亲节点上面来的最远的点的距离。

代码

cpp 复制代码
class Solution {
    vector<vector<int>> e;
    vector<int> f, g, h;
    int M;

    void dfs(int u, int p) {
        for (int v: e[u]) {
            if (v == p) continue;
            dfs(v, u);
            if (f[v] + 1 > f[u]) {
                g[u] = f[u];
                f[u] = f[v] + 1;
            } else if (f[v] + 1 >= g[u]) g[u] = f[v] + 1;
        }
        // cout << u << " " << f[u] << " " << g[u] << endl;
    }

    void dfs2(int u, int p) {
        for (int v: e[u]) {
            if (v == p) continue;
            if (f[v] + 1 == f[u]) {
                h[v] = max(h[u], g[u]) + 1;
            } else {
                h[v] = max(h[u], f[u]) + 1;
            }
            if (M > max(h[v], f[v])) M = max(h[v], f[v]);
            dfs2(v, u);
        }
        //cout << u << " " << h[u] << " " << f[u] << endl;
    }


public:
    vector<int> findMinHeightTrees(int n, vector<vector<int>> &edges) {
        f = vector<int>(n);
        g = vector<int>(n);
        h = vector<int>(n);
        e = vector<vector<int>>(n);
        for (auto edge: edges) {
            e[edge[0]].push_back(edge[1]);
            e[edge[1]].push_back(edge[0]);
        }
        dfs(0, -1);
        M = f[0];
        dfs2(0, -1);
        vector<int> ans;
        for (int i = 0; i < n; i++) {
            if (M == max(h[i], f[i])) ans.push_back(i);
        }
        return ans;
    }
};

结果

3 进阶

用拓扑排序,依次去掉度为 1 的点,最后一轮留下来的即为最终要求的节点。

cpp 复制代码
class Solution {

public:
    vector<int> findMinHeightTrees(int n, vector<vector<int>> &edges) {
        if(edges.empty()) return {0};
        vector<vector<int>> e(n);
        vector<int> degree(n);
        for (auto edge: edges) {
            e[edge[0]].push_back(edge[1]);
            e[edge[1]].push_back(edge[0]);
            degree[edge[0]]++;
            degree[edge[1]]++;
        }


        vector<int> stk[2];
        for (int i = 0; i < n; i++) {
            if (degree[i] == 1) stk[0].push_back(i);
        }
        int i = 0;
        for (; !stk[i & 1].empty(); i++) {
            stk[i + 1 & 1].clear();
            for (int u: stk[i & 1]) {
                //cout << u;
                for (int v: e[u]) {
                    if (--degree[v] == 1) stk[i + 1 & 1].push_back(v);
                }
            }
        }
        return stk[i + 1 & 1];
    }
};
相关推荐
木叶丸几秒前
编程开发中,那些你必须掌握的基本概念
前端·数据结构·编程语言
Mr.Winter`4 分钟前
轨迹优化 | 基于激光雷达的欧氏距离场ESDF地图构建(附ROS C++仿真)
c++·人工智能·机器人·自动驾驶·ros·ros2·具身智能
csdn_aspnet7 分钟前
C++ n条水平平行线与m条垂直平行线相交的平行四边形的数量
c++
Y1nhl19 分钟前
力扣_链表_python版本
开发语言·python·算法·leetcode·链表·职场和发展
qq_4017004135 分钟前
C语言中位运算以及获取低8位和高8位、高低位合并
c语言·开发语言·算法
CoovallyAIHub38 分钟前
YOLO模型优化全攻略:从“准”到“快”,全靠这些招!
深度学习·算法·计算机视觉
闻缺陷则喜何志丹43 分钟前
【BFS】 P10864 [HBCPC2024] Genshin Impact Startup Forbidden II|普及+
c++·算法·宽度优先·洛谷
MicroTech20251 小时前
微算法科技(NASDAQ: MLGO)探索Grover量子搜索算法,利用量子叠加和干涉原理,实现在无序数据库中快速定位目标信息的效果。
数据库·科技·算法
qianbo_insist1 小时前
c++ python 共享内存
开发语言·c++·python