题目描述
有一棵有 n
个节点,编号从 0
到 n - 1
的 无向 树。给定一个长度为 n - 1
的整数数组 edges
,其中 edges[i] = [ui, vi]
表示树中的 ui
和 vi
之间有一条边。
一开始,所有 节点都 未标记。之后的每一秒,你需要标记所有 至少 有一个已标记节点相邻的未标记节点。
返回一个数组 nodes
,表示在时刻 t = 0
标记了节点 i
,那么树中最后标记的节点是 nodes[i]
。如果对于任意节点 i
有多个 nodes[i]
,你可以选择 任意 一个作为答案。
示例 1:
输入:edges = [[0,1],[0,2]]
输出:[2,2,1]
解释:
- 对于
i = 0
,节点以如下序列标记:[0] -> [0,1,2]
。1 和 2 都可以是答案。
- 对于
i = 1
,节点以如下序列标记:[1] -> [0,1] -> [0,1,2]
。节点 2 最后被标记。
- 对于
i = 2
,节点以如下序列标记:[2] -> [0,2] -> [0,1,2]
。节点 1 最后被标记。
示例 2:
输入:edges = [[0,1]]
输出:[1,0]
解释:
- 对于
i = 0
,节点以如下序列被标记:[0] -> [0,1]
。
- 对于
i = 1
,节点以如下序列被标记:[1] -> [0,1]
。
示例 3:
输入:edges = [[0,1],[0,2],[2,3],[2,4]]
输出:[3,3,1,1,1]
解释:
- 对于
i = 0
,节点以如下序列被标记:[0] -> [0,1,2] -> [0,1,2,3,4]
。
- 对于
i = 1
,节点以如下序列被标记:[1] -> [0,1] -> [0,1,2] -> [0,1,2,3,4]
。
- 对于
i = 2
,节点以如下序列被标记:[2] -> [0,2,3,4] -> [0,1,2,3,4]
。
- 对于
i = 3
,节点以如下序列被标记:[3] -> [2,3] -> [0,2,3,4] -> [0,1,2,3,4]
。
- 对于
i = 4
,节点以如下序列被标记:[4] -> [2,4] -> [0,2,3,4] -> [0,1,2,3,4]
。
提示:
2 <= n <= 105
edges.length == n - 1
edges[i].length == 2
0 <= edges[i][0], edges[i][1] <= n - 1
- 输入保证
edges
形成一棵合法的树。
解法
方法一:求树的直径 + DFS
根据题目描述,最后一个被标记的节点一定是树的直径的一个端点,因为树的直径上的节点到直径上的任意一个节点的距离最大。
我们可以从任意一个节点开始进行深度优先搜索,找到距离最远的节点 $a$,这个节点就是树的直径的一个端点。
然后从节点 $a$ 开始进行深度优先搜索,找到距离最远的节点 $b$,这个节点就是树的直径的另一个端点,在这个过程中,我们计算出了每个节点到节点 $a$ 的距离,记为 $\textit{dist2}$。
接着从节点 $b$ 开始进行深度优先搜索,计算出每个节点到节点 $b$ 的距离,记为 $\textit{dist3}$。
那么,对于每一个节点 $i$,如果 $\textit{dist2}[i] > \textit{dist3}[i]$,那么节点 $a$ 到节点 $i$ 的距离更远,所以节点 $a$ 是最后一个被标记的节点;否则,节点 $b$ 是最后一个被标记的节点。
时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 是节点的数量。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 | class Solution:
def lastMarkedNodes(self, edges: List[List[int]]) -> List[int]:
def dfs(i: int, fa: int, dist: List[int]):
for j in g[i]:
if j != fa:
dist[j] = dist[i] + 1
dfs(j, i, dist)
n = len(edges) + 1
g = [[] for _ in range(n)]
for u, v in edges:
g[u].append(v)
g[v].append(u)
dist1 = [-1] * n
dist1[0] = 0
dfs(0, -1, dist1)
a = dist1.index(max(dist1))
dist2 = [-1] * n
dist2[a] = 0
dfs(a, -1, dist2)
b = dist2.index(max(dist2))
dist3 = [-1] * n
dist3[b] = 0
dfs(b, -1, dist3)
return [a if x > y else b for x, y in zip(dist2, dist3)]
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52 | class Solution {
private List<Integer>[] g;
public int[] lastMarkedNodes(int[][] edges) {
int n = edges.length + 1;
g = new List[n];
Arrays.setAll(g, k -> new ArrayList<>());
for (var e : edges) {
int u = e[0], v = e[1];
g[u].add(v);
g[v].add(u);
}
int[] dist1 = new int[n];
dist1[0] = 0;
dfs(0, -1, dist1);
int a = maxNode(dist1);
int[] dist2 = new int[n];
dist2[a] = 0;
dfs(a, -1, dist2);
int b = maxNode(dist2);
int[] dist3 = new int[n];
dist3[b] = 0;
dfs(b, -1, dist3);
int[] ans = new int[n];
for (int i = 0; i < n; ++i) {
ans[i] = dist2[i] > dist3[i] ? a : b;
}
return ans;
}
private void dfs(int i, int fa, int[] dist) {
for (int j : g[i]) {
if (j != fa) {
dist[j] = dist[i] + 1;
dfs(j, i, dist);
}
}
}
private int maxNode(int[] dist) {
int mx = 0;
for (int i = 0; i < dist.length; ++i) {
if (dist[mx] < dist[i]) {
mx = i;
}
}
return mx;
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40 | class Solution {
public:
vector<int> lastMarkedNodes(vector<vector<int>>& edges) {
int n = edges.size() + 1;
g.resize(n);
for (const auto& e : edges) {
int u = e[0], v = e[1];
g[u].push_back(v);
g[v].push_back(u);
}
vector<int> dist1(n);
dfs(0, -1, dist1);
int a = max_element(dist1.begin(), dist1.end()) - dist1.begin();
vector<int> dist2(n);
dfs(a, -1, dist2);
int b = max_element(dist2.begin(), dist2.end()) - dist2.begin();
vector<int> dist3(n);
dfs(b, -1, dist3);
vector<int> ans;
for (int i = 0; i < n; ++i) {
ans.push_back(dist2[i] > dist3[i] ? a : b);
}
return ans;
}
private:
vector<vector<int>> g;
void dfs(int i, int fa, vector<int>& dist) {
for (int j : g[i]) {
if (j != fa) {
dist[j] = dist[i] + 1;
dfs(j, i, dist);
}
}
}
};
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47 | func lastMarkedNodes(edges [][]int) (ans []int) {
n := len(edges) + 1
g := make([][]int, n)
for _, e := range edges {
u, v := e[0], e[1]
g[u] = append(g[u], v)
g[v] = append(g[v], u)
}
var dfs func(int, int, []int)
dfs = func(i, fa int, dist []int) {
for _, j := range g[i] {
if j != fa {
dist[j] = dist[i] + 1
dfs(j, i, dist)
}
}
}
maxNode := func(dist []int) int {
mx := 0
for i, d := range dist {
if dist[mx] < d {
mx = i
}
}
return mx
}
dist1 := make([]int, n)
dfs(0, -1, dist1)
a := maxNode(dist1)
dist2 := make([]int, n)
dfs(a, -1, dist2)
b := maxNode(dist2)
dist3 := make([]int, n)
dfs(b, -1, dist3)
for i, x := range dist2 {
if x > dist3[i] {
ans = append(ans, a)
} else {
ans = append(ans, b)
}
}
return
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33 | function lastMarkedNodes(edges: number[][]): number[] {
const n = edges.length + 1;
const g: number[][] = Array.from({ length: n }, () => []);
for (const [u, v] of edges) {
g[u].push(v);
g[v].push(u);
}
const dfs = (i: number, fa: number, dist: number[]) => {
for (const j of g[i]) {
if (j !== fa) {
dist[j] = dist[i] + 1;
dfs(j, i, dist);
}
}
};
const dist1: number[] = Array(n).fill(0);
dfs(0, -1, dist1);
const a = dist1.indexOf(Math.max(...dist1));
const dist2: number[] = Array(n).fill(0);
dfs(a, -1, dist2);
const b = dist2.indexOf(Math.max(...dist2));
const dist3: number[] = Array(n).fill(0);
dfs(b, -1, dist3);
const ans: number[] = [];
for (let i = 0; i < n; ++i) {
ans.push(dist2[i] > dist3[i] ? a : b);
}
return ans;
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37 | /**
* @param {number[][]} edges
* @return {number[]}
*/
var lastMarkedNodes = function (edges) {
const n = edges.length + 1;
const g = Array.from({ length: n }, () => []);
for (const [u, v] of edges) {
g[u].push(v);
g[v].push(u);
}
const dfs = (i, fa, dist) => {
for (const j of g[i]) {
if (j !== fa) {
dist[j] = dist[i] + 1;
dfs(j, i, dist);
}
}
};
const dist1 = Array(n).fill(0);
dfs(0, -1, dist1);
const a = dist1.indexOf(Math.max(...dist1));
const dist2 = Array(n).fill(0);
dfs(a, -1, dist2);
const b = dist2.indexOf(Math.max(...dist2));
const dist3 = Array(n).fill(0);
dfs(b, -1, dist3);
const ans = [];
for (let i = 0; i < n; ++i) {
ans.push(dist2[i] > dist3[i] ? a : b);
}
return ans;
};
|