算法概论week7 | leetcode 310. Minimum Height Trees

目录

  • 题目描述
  • 分析
  • 代码

题目描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


分析

这道题很容易想到用dfs分别求出每棵树的高度,再取最小值,但是这样复杂度太高了,最后一个样例怎么都不能通过,于是只好另辟蹊径,参考了别人的博客,学到了一种新的算法,就是逐步删除叶子节点,直到没有可删除的节点,剩下的这个/些节点就是答案。

首先用map把图表示成有向图:

	map<int, set<int>> mat;
        for(auto i : edges) {
            mat[i.first].insert(i.second);
            mat[i.second].insert(i.first);
        }

在这里,出度为一的点就是叶子节点:

	vector<int> leaves;
        for(auto i : mat) {
            if(i.second.size() == 1) {
                leaves.push_back(i.first);
            }
        }

然后开始删除叶子节点,在删除节点的同时,更新与之相连的其它节点,同时用另一个数组存储新产生的叶子节点,循环往复,直到只剩下一个或两个节点:

	while(n > 2) {
            n -= leaves.size();
            vector<int> new_leaves;
            for(auto i : leaves) {
                auto next = mat[i];
                for(auto j : next) {
                    mat[i].erase(j);
                    mat[j].erase(i);
                    if(mat[j].size() == 1) {
                        new_leaves.push_back(j);
                    }
                }
            }
            leaves = new_leaves;
        }

代码

class Solution {
public:
    vector<int> findMinHeightTrees(int n, vector<pair<int, int>>& edges) {
        if(n == 1) {
            return {0};
        }
        
        map<int, set<int>> mat;
        for(auto i : edges) {
            mat[i.first].insert(i.second);
            mat[i.second].insert(i.first);
        }
        
        vector<int> leaves;
        for(auto i : mat) {
            if(i.second.size() == 1) {
                leaves.push_back(i.first);
            }
        }
        
        while(n > 2) {
            n -= leaves.size();
            vector<int> new_leaves;
            for(auto i : leaves) {
                auto next = mat[i];
                for(auto j : next) {
                    mat[i].erase(j);
                    mat[j].erase(i);
                    if(mat[j].size() == 1) {
                        new_leaves.push_back(j);
                    }
                }
            }
            leaves = new_leaves;
        }
        
        return leaves;
    }
    
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值