/* * 310. Minimum Height Trees * 2016-3-29 by Mingyang * 同样的方法构建无向图 * 这里运用的一个层层剥丝的方式,一层一层的来,去掉不要的 * 我最先想到的解法是遍历的点,以每个点都当做根节点,算出高度,然后找出最小的,发现大家推崇的方法是一个类似剥洋葱的方法, * 就是一层一层的褪去叶节点,最后剩下的一个或两个节点就是我们要求的最小高度树的根节点,这种思路非常的巧妙,而且实现起来也不难, * 跟之前那到课程清单的题一样,我们需要建立一个图g,是一个二维数组,其中g[i]是一个一维数组,保存了i节点可以到达的所有节点。 * 还需要一个一维数组d用来保存各个节点的入度信息,其中d[i]表示i节点的入度数。我们的目标是删除所有的叶节点,叶节点的入度为1, * 所以我们开始将所有入度为1的节点(叶节点)都存入到一个队列queue中,然后我们遍历每一个叶节点,通过图来找到和其相连的节点, * 将该节点的入度减1,如果该节点的入度减到1了,说明此节点也也变成一个叶节点了,加入队列中,再下一轮删除。那么我们删到什么时候呢, * 当节点数小于等于2时候停止,此时剩下的一个或两个节点就是我们要求的最小高度树的根节点啦 */ public List<Integer> findMinHeightTrees(int n, int[][] edges) { if (n == 1) return Collections.singletonList(0); List<Set<Integer>> adj = new ArrayList<Set<Integer>>(n); for (int i = 0; i < n; ++i) adj.add(new HashSet<Integer>()); for (int[] edge : edges) { adj.get(edge[0]).add(edge[1]); adj.get(edge[1]).add(edge[0]); } List<Integer> leaves = new ArrayList<Integer>(); for (int i = 0; i < n; ++i) if (adj.get(i).size() == 1) leaves.add(i); //这里是找到叶子节点,每一个叶子节点的上一层节点,砍掉回来的路 while (n > 2) { n -= leaves.size(); List<Integer> newLeaves = new ArrayList<Integer>(); for (int i : leaves) { int j = adj.get(i).iterator().next(); adj.get(j).remove(i); if (adj.get(j).size() == 1) newLeaves.add(j); } leaves = newLeaves; } return leaves; }
时间: 2024-10-08 12:51:36