LeetCode 3203. Find Minimum Diameter After Merging Two Trees

🔗 https://leetcode.com/problems/find-minimum-diameter-after-merging-two-trees

题目

  • 合并两个 tree,使得 tree 的直径最小,返回最小值
  • tree 的直径,是任意两个 node 之间 edge 条数的最大值

思路

  • 合并后的 tree 的直径的最小值,是以下情况的最大值
    • tree 1 的直径
    • tree 2 的直径
    • tree 1 最低高度 + tree 2 最低高度 + 1
  • 算 tree 的最低高度的朴素算法是,枚举起始点,dfs 或者 bfs 计算其其高度。tree 的直径是,上述高度的最大值。这样的算法时间复杂度高,会 TLE

  • tree 的最低高度为 tree 的直径/2 的 ceil,tree 的直径可以通过两遍 bfs 计算得出
  • 假设 tree 的直径如图所示,随意一个 node 开始 bfs ,必然会找到 tree 的直径的一个端点,对这个端点进行 bfs 即可求出直径

在这里插入图片描述


  • dfs 求直径为以下的最大值
    • node 的 substree 的直径
    • node 的两个最大 depth 之和

代码

class Solution {
public:
    int build(vector<vector<int>>& edges) {
        int n = edges.size();
        vector<vector<int>> adj(n + 1);
        for (auto edge : edges) {
            adj[edge[0]].push_back(edge[1]);
            adj[edge[1]].push_back(edge[0]);
        }
        vector<bool> visited(n+1);
        queue<int> que;
        que.push(0);
        int end = 0;
        visited[0] = true;
        while (!que.empty()) {
            end = que.front();
            int size = que.size();
            while (size--) {
                int node = que.front(); que.pop();
                for (int i = 0; i < adj[node].size(); i++) {
                    if (visited[adj[node][i]]) continue;
                    que.push(adj[node][i]);
                    visited[adj[node][i]] = true;
                }
            }
        }

        std::fill(visited.begin(), visited.end(), false);
        que.push(end);
        visited[end] = true;
        int dia = 0;

        while (!que.empty()) {
            dia++;
            int size = que.size();
            while (size--) {
                int node = que.front(); que.pop();
                for (int i = 0; i < adj[node].size(); i++) {
                    if (visited[adj[node][i]]) continue;
                    que.push(adj[node][i]);
                    visited[adj[node][i]] = true;
                }
            }
        }

        return --dia;
        
    }
    int minimumDiameterAfterMerge(vector<vector<int>>& edges1, vector<vector<int>>& edges2) {
        int dia_1 = build(edges1);
        int dia_2 = build(edges2);
        
        return max(dia_1/2 + dia_1%2 + dia_2/2 + dia_2 %2 + 1, max(dia_1, dia_2));
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值