310. 最小高度树

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

给你一棵包含 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]

题解:对于树结构,这题主要的问题是如何求解树的深度。然后对每一个节点当根节点进行依次求解,然后比较大小。对于树的深度,我们可以使用深度优先遍历和广度优先遍历,原理都是一样的。在此以广度优先遍历为例,准备一个队列,存储兄弟节点的信息,然后要确保每一个节点都要访问而且不能重复访问,可以使用一个数组统计每个节点是否已访问。这就是这题的暴力求解,优化算法自己理解不了。(现在Leetcode的中等题已经这样着了。。。。)

class Solution {
    public static List<Integer> findMinHeightTrees(int n, int[][] edges) {
        List<Integer> target = new ArrayList<>();
        ArrayList<Integer>[] lists = new ArrayList[n];
        for (int[] edge : edges) {
            ArrayList<Integer> tmp0 = lists[edge[0]];
            ArrayList<Integer> tmp1 = lists[edge[1]];
            if (tmp0 == null) {
                tmp0 = new ArrayList<Integer>();
                lists[edge[0]] = tmp0;
            }
            tmp0.add(edge[1]);
            if (tmp1 == null) {
                tmp1 = new ArrayList<Integer>();
                lists[edge[1]] = tmp1;
            }
            tmp1.add(edge[0]);
        }
        for (int i = 0; i < n; i++) {
            Queue<Integer> queue = new PriorityQueue<>();
            queue.add(i);
            int[] visted = new int[n];
            //记录当前层
            Map<Integer, Integer> map = new HashMap<>();
            map.put(i, 1);
            int Height = 0;
            while (!queue.isEmpty()) {
                Integer poll = queue.poll();
                if(visted[poll]!=1) {
                    ArrayList<Integer> list = lists[poll];
                    if (list != null) {
                        for (Integer t : list) {
                            if(visted[t]!=1) {
                                queue.add(t);
                                map.put(t, map.get(poll) + 1);
                                Height = Math.max(Height, map.get(poll) + 1);
                            }
                        }
                    }
                }
                visted[poll] = 1;
            }
            if (target.isEmpty()) {
                target.add(Height);
                target.add(i);
            } else {
                Integer i1 = target.get(0);
                if(i1==Height)
                    target.add(i);
                else if (i1 > Height) {
                    target.clear();
                    target.add(Height);
                    target.add(i);
                }
            }
        }
        target.remove(0);
        return target;
    }
}

官方解答是先证明树中的最长两个结点,根节点一定在这两个结点的路径上。在此就不贴官方代码了,大家感兴趣的可以去看看。

  • 8
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值