[路飞]_310. 最小高度树

「这是我参与2022首次更文挑战的第36天,活动详情查看:2022首次更文挑战

310. 最小高度树

题目

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

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

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

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

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

示例1

image.png

输入:n = 4, edges = [[1,0],[1,2],[1,3]]
输出:[1]
解释:如图所示,当根是标签为 1 的节点时,树的高度是 1 ,这是唯一的最小高度树。
复制代码

示例2

image.png

输入: n = 6, edges = [[3,0],[3,1],[3,2],[3,4],[5,4]]
输出: [3,4]
复制代码

题解

BFS + 哈希表

度的概念

  • -个节点与另一个节点相连,我们就说这两个节点的度分别是1
  • 如果一个节点和两个节点相连,我们就说这个节点的度是2
  • 如果一个节点和9个节点相连,我们就说这个节点的度是9

了解了度的概念,接下来来理解本题

分析示例1

示例1中的数据 n = 4 , e d g e s = [ [ 1 , 0 ] , [ 1 , 2 ] , [ 1 , 3 ] ] n = 4, edges = [[1,0],[1,2],[1,3]]

构建节点与度的关系

graph TD
1 --> 2 & 0 & 3
  • 节点0的度为1;
  • 节点1的度为3;
  • 节点2的度为1;
  • 节点3的度为1;

将度为1的节点删除,并且删除节点的时候,与节点相连的另一个节点度值-1;结果:

  • 节点0的度为0;
  • 节点1的度为1;
  • 节点2的度为0;
  • 节点3的度为0;

返回节点1即可

分析示例2

示例2中的数据 n = 6 , e d g e s = [ [ 3 , 0 ] , [ 3 , 1 ] , [ 3 , 2 ] , [ 3 , 4 ] , [ 5 , 4 ] ] n = 6, edges = [[3,0],[3,1],[3,2],[3,4],[5,4]]

构建节点与度的关系:

  • 节点0的度为1;
  • 节点1的度为1;
  • 节点2的度为1;
  • 节点3的度为4;
  • 节点4的度为2;
  • 节点5的度为1;

将度为1的节点删除,并且删除节点的时候,与节点相连的另一个节点度值-1;结果:

  • 节点0的度为0;
  • 节点1的度为0;
  • 节点2的度为0;
  • 节点3的度为1;
  • 节点4的度为1;
  • 节点5的度为0;

返回度为1的节点即可

总结

统计节点与节点关系,节点的度;

  • 将节点度为1的节点存放到队列 s t a c k stack
  • 将 stack 队列度为1的节点删除,并与节点相连的另一个节点度值-1
  • 如果剩余节点中度为1,继续添加到队列 s t a c k stack
  • 返回最后一层 队列 s t a c k stack

根据上述思路编辑代码如下:

var findMinHeightTrees = function (n, edges) {
  if (n === 1) return [0];
  // 构建图的入度信息
  const map = {};
  const list = Array(n).fill(0);
  edges.forEach((v) => {
    const [a, b] = v;
    list[a] += 1;
    list[b] += 1;
    if (map[a]) {
      map[a].push(b);
    } else {
      map[a] = [b];
    }

    if (map[b]) {
      map[b].push(a);
    } else {
      map[b] = [a];
    }
  });

  // 将入度为0的节点塞入队列
  let stack = [];
  for (let i = 0; i < list.length; i++) {
    if (list[i] === 1) stack.push(i);
  }

  // 将入度为1的节点删除
  let result = [];
  while (stack.length) {
    result = [];
    const len = stack.length;
    for (let i = 0; i < len; i++) {
      const idx = stack[i];
      result.push(idx);
      list[idx] -= 1;
      const array = map[idx];
      for (let j = 0; j < array.length; j++) {
        list[array[j]] -= 1;
        if (list[array[j]] === 1) stack.push(array[j]);
      }
    }

    stack = stack.slice(len);
  }
  return result;
};
复制代码

结语

作者水平有限,如有不足欢迎指正;任何意见和建议欢迎评论区浏览讨论

猜你喜欢

转载自juejin.im/post/7067520336308371492
今日推荐