comments | difficulty | edit_url | tags | ||
---|---|---|---|---|---|
true |
Hard |
|
There exists an undirected tree with n
nodes numbered 0
to n - 1
. You are given a 2D integer array edges
of length n - 1
, where edges[i] = [ui, vi]
indicates that there is an edge between nodes ui
and vi
in the tree.
Initially, all nodes are unmarked. After every second, you mark all unmarked nodes which have at least one marked node adjacent to them.
Return an array nodes
where nodes[i]
is the last node to get marked in the tree, if you mark node i
at time t = 0
. If nodes[i]
has multiple answers for any node i
, you can choose any one answer.
Example 1:
Input: edges = [[0,1],[0,2]]
Output: [2,2,1]
Explanation:
- For
i = 0
, the nodes are marked in the sequence:[0] -> [0,1,2]
. Either 1 or 2 can be the answer. - For
i = 1
, the nodes are marked in the sequence:[1] -> [0,1] -> [0,1,2]
. Node 2 is marked last. - For
i = 2
, the nodes are marked in the sequence:[2] -> [0,2] -> [0,1,2]
. Node 1 is marked last.
Example 2:
Input: edges = [[0,1]]
Output: [1,0]
Explanation:
- For
i = 0
, the nodes are marked in the sequence:[0] -> [0,1]
. - For
i = 1
, the nodes are marked in the sequence:[1] -> [0,1]
.
Example 3:
Input: edges = [[0,1],[0,2],[2,3],[2,4]]
Output: [3,3,1,1,1]
Explanation:
- For
i = 0
, the nodes are marked in the sequence:[0] -> [0,1,2] -> [0,1,2,3,4]
. - For
i = 1
, the nodes are marked in the sequence:[1] -> [0,1] -> [0,1,2] -> [0,1,2,3,4]
. - For
i = 2
, the nodes are marked in the sequence:[2] -> [0,2,3,4] -> [0,1,2,3,4]
. - For
i = 3
, the nodes are marked in the sequence:[3] -> [2,3] -> [0,2,3,4] -> [0,1,2,3,4]
. - For
i = 4
, the nodes are marked in the sequence:[4] -> [2,4] -> [0,2,3,4] -> [0,1,2,3,4]
.
Constraints:
2 <= n <= 105
edges.length == n - 1
edges[i].length == 2
0 <= edges[i][0], edges[i][1] <= n - 1
- The input is generated such that
edges
represents a valid tree.
According to the problem description, the last marked node must be one endpoint of the tree's diameter, because the distance from any node on the diameter to any other node on the diameter is the greatest.
We can start a depth-first search (DFS) from any node to find the farthest node
Then, starting from node
Next, we perform a depth-first search starting from node
For each node
The time complexity is
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)]
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;
}
}
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);
}
}
}
};
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
}
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;
}
/**
* @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;
};