「这是我参与2022首次更文挑战的第36天,活动详情查看:2022首次更文挑战」
题目
树是一个无向图,其中任何两个顶点只通过一条路径连接。 换句话说,一个任何没有简单环路的连通图都是一棵树。
给你一棵包含 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]
复制代码
题解
BFS + 哈希表
度的概念
- -个节点与另一个节点相连,我们就说这两个节点的度分别是1
- 如果一个节点和两个节点相连,我们就说这个节点的度是2
- 如果一个节点和9个节点相连,我们就说这个节点的度是9
了解了度的概念,接下来来理解本题
分析示例1
示例1中的数据
构建节点与度的关系
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中的数据
构建节点与度的关系:
- 节点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的节点存放到队列 中
- 将 stack 队列度为1的节点删除,并与节点相连的另一个节点度值-1
- 如果剩余节点中度为1,继续添加到队列 中
- 返回最后一层 队列
根据上述思路编辑代码如下:
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;
};
复制代码
结语
作者水平有限,如有不足欢迎指正;任何意见和建议欢迎评论区浏览讨论