Skip to content

Commit a0dfaa9

Browse files
committed
feat: add solutions to lc problem: No.1245
No.1245.Tree Diameter
1 parent c0c3ffe commit a0dfaa9

File tree

7 files changed

+657
-2
lines changed

7 files changed

+657
-2
lines changed

solution/1200-1299/1245.Tree Diameter/README.md

Lines changed: 152 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,22 +49,173 @@
4949

5050
<!-- 这里可写通用的实现逻辑 -->
5151

52+
两次 DFS。
53+
54+
首先对任意一个结点做 DFS 求出最远的结点,然后以这个结点为根结点再做 DFS 到达另一个最远结点。第一次 DFS 到达的结点可以证明一定是这个图的直径的一端,第二次 DFS 就会达到另一端。下面来证明这个定理。
55+
56+
定理:在一个连通无向无环图中,以任意结点出发所能到达的最远结点,一定是该图直径的端点之一。
57+
58+
证明:假设这条直径是 δ(s, t)。分两种情况:
59+
60+
1. 当出发结点 y 在 δ(s, t) 时,假设到达的最远结点 z 不是 s, t 中的任一个。这时将 δ(y, z) 与不与之重合的 δ(y, s) 拼接(也可以假设不与之重合的是直径的另一个方向),可以得到一条更长的直径,与前提矛盾。
61+
1. 当出发结点 y 不在 δ(s, t) 上时,分两种情况:
62+
63+
- 当 y 到达的最远结点 z 横穿 δ(s, t) 时,记与之相交的结点为 x。此时有 δ(y, z) = δ(y, x) + δ(x, z)。而此时 δ(y, z) > δ(y, t),故可得 δ(x, z) > δ(x, t)。由 1 的结论可知该假设不成立。
64+
- 当 y 到达的最远结点 z 与 δ(s, t) 不相交时,定义从 y 开始到 t 结束的简单路径上,第一个同时也存在于简单路径 δ(s, t) 上的结点为 x,最后一个存在于简单路径 δ(y, z) 上的结点为 x’。如下图。那么根据假设,有 δ(y, z) ≥ δ(y, t) => δ(x', z) ≥ δ(x', x) + δ(x, t)。既然这样,那么 δ(x, z) ≥ δ(x, t),和 δ(s, t) 对应着直径这一前提不符,故 y 的最远结点 z 不可能在 s 到 t 这个直径对应的路外面。
65+
66+
<img alt="" src="https://cdn.jsdelivr.net/gh/doocs/leetcode@main/solution/1200-1299/1245.Tree%20Diameter/images/tree-diameter.svg">
67+
68+
因此定理成立。
69+
5270
<!-- tabs:start -->
5371

5472
### **Python3**
5573

5674
<!-- 这里可写当前语言的特殊实现逻辑 -->
5775

5876
```python
59-
77+
class Solution:
78+
def treeDiameter(self, edges: List[List[int]]) -> int:
79+
def dfs(u, t):
80+
nonlocal ans, vis, d, next
81+
if vis[u]:
82+
return
83+
vis[u] = True
84+
for v in d[u]:
85+
dfs(v, t + 1)
86+
if ans < t:
87+
ans = t
88+
next = u
89+
90+
d = defaultdict(set)
91+
vis = [False] * (len(edges) + 1)
92+
for u, v in edges:
93+
d[u].add(v)
94+
d[v].add(u)
95+
ans = 0
96+
next = 0
97+
dfs(edges[0][0], 0)
98+
vis = [False] * (len(edges) + 1)
99+
dfs(next, 0)
100+
return ans
60101
```
61102

62103
### **Java**
63104

64105
<!-- 这里可写当前语言的特殊实现逻辑 -->
65106

66107
```java
108+
class Solution {
109+
private Map<Integer, Set<Integer>> g;
110+
private boolean[] vis;
111+
private int next;
112+
private int ans;
113+
114+
public int treeDiameter(int[][] edges) {
115+
int n = edges.length;
116+
ans = 0;
117+
g = new HashMap<>();
118+
for (int[] e : edges) {
119+
g.computeIfAbsent(e[0], k -> new HashSet<>()).add(e[1]);
120+
g.computeIfAbsent(e[1], k -> new HashSet<>()).add(e[0]);
121+
}
122+
vis = new boolean[n + 1];
123+
next = edges[0][0];
124+
dfs(next, 0);
125+
vis = new boolean[n + 1];
126+
dfs(next, 0);
127+
return ans;
128+
}
129+
130+
private void dfs(int u, int t) {
131+
if (vis[u]) {
132+
return;
133+
}
134+
vis[u] = true;
135+
if (ans < t) {
136+
ans = t;
137+
next = u;
138+
}
139+
for (int v : g.get(u)) {
140+
dfs(v, t + 1);
141+
}
142+
}
143+
}
144+
```
145+
146+
### **C++**
147+
148+
```cpp
149+
class Solution {
150+
public:
151+
unordered_map<int, unordered_set<int>> g;
152+
vector<bool> vis;
153+
int ans;
154+
int next;
155+
156+
int treeDiameter(vector<vector<int>>& edges) {
157+
for (auto& e : edges)
158+
{
159+
g[e[0]].insert(e[1]);
160+
g[e[1]].insert(e[0]);
161+
}
162+
int n = edges.size();
163+
ans = 0;
164+
vis.resize(n + 1);
165+
next = edges[0][0];
166+
dfs(next, 0);
167+
vis.assign(vis.size(), false);
168+
dfs(next, 0);
169+
return ans;
170+
}
171+
172+
void dfs(int u, int t) {
173+
if (vis[u]) return;
174+
vis[u] = true;
175+
if (ans < t)
176+
{
177+
ans = t;
178+
next = u;
179+
}
180+
for (int v : g[u]) dfs(v, t + 1);
181+
}
182+
};
183+
```
67184
185+
### **Go**
186+
187+
```go
188+
func treeDiameter(edges [][]int) int {
189+
n := len(edges)
190+
g := make(map[int][]int)
191+
for _, e := range edges {
192+
g[e[0]] = append(g[e[0]], e[1])
193+
g[e[1]] = append(g[e[1]], e[0])
194+
}
195+
vis := make(map[int]bool, n+1)
196+
ans := 0
197+
next := edges[0][0]
198+
var dfs func(u, t int)
199+
dfs = func(u, t int) {
200+
if vis[u] {
201+
return
202+
}
203+
vis[u] = true
204+
if ans < t {
205+
ans = t
206+
next = u
207+
}
208+
if vs, ok := g[u]; ok {
209+
for _, v := range vs {
210+
dfs(v, t+1)
211+
}
212+
}
213+
}
214+
dfs(next, 0)
215+
vis = make(map[int]bool, n+1)
216+
dfs(next, 0)
217+
return ans
218+
}
68219
```
69220

70221
### **...**

solution/1200-1299/1245.Tree Diameter/README_EN.md

Lines changed: 134 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,146 @@ A longest path of the tree is the path 3 - 2 - 1 - 4 - 5.
4848
### **Python3**
4949

5050
```python
51-
51+
class Solution:
52+
def treeDiameter(self, edges: List[List[int]]) -> int:
53+
def dfs(u, t):
54+
nonlocal ans, vis, d, next
55+
if vis[u]:
56+
return
57+
vis[u] = True
58+
for v in d[u]:
59+
dfs(v, t + 1)
60+
if ans < t:
61+
ans = t
62+
next = u
63+
64+
d = defaultdict(set)
65+
vis = [False] * (len(edges) + 1)
66+
for u, v in edges:
67+
d[u].add(v)
68+
d[v].add(u)
69+
ans = 0
70+
next = 0
71+
dfs(edges[0][0], 0)
72+
vis = [False] * (len(edges) + 1)
73+
dfs(next, 0)
74+
return ans
5275
```
5376

5477
### **Java**
5578

5679
```java
80+
class Solution {
81+
private Map<Integer, Set<Integer>> g;
82+
private boolean[] vis;
83+
private int next;
84+
private int ans;
85+
86+
public int treeDiameter(int[][] edges) {
87+
int n = edges.length;
88+
ans = 0;
89+
g = new HashMap<>();
90+
for (int[] e : edges) {
91+
g.computeIfAbsent(e[0], k -> new HashSet<>()).add(e[1]);
92+
g.computeIfAbsent(e[1], k -> new HashSet<>()).add(e[0]);
93+
}
94+
vis = new boolean[n + 1];
95+
next = edges[0][0];
96+
dfs(next, 0);
97+
vis = new boolean[n + 1];
98+
dfs(next, 0);
99+
return ans;
100+
}
101+
102+
private void dfs(int u, int t) {
103+
if (vis[u]) {
104+
return;
105+
}
106+
vis[u] = true;
107+
if (ans < t) {
108+
ans = t;
109+
next = u;
110+
}
111+
for (int v : g.get(u)) {
112+
dfs(v, t + 1);
113+
}
114+
}
115+
}
116+
```
117+
118+
### **C++**
119+
120+
```cpp
121+
class Solution {
122+
public:
123+
unordered_map<int, unordered_set<int>> g;
124+
vector<bool> vis;
125+
int ans;
126+
int next;
127+
128+
int treeDiameter(vector<vector<int>>& edges) {
129+
for (auto& e : edges)
130+
{
131+
g[e[0]].insert(e[1]);
132+
g[e[1]].insert(e[0]);
133+
}
134+
int n = edges.size();
135+
ans = 0;
136+
vis.resize(n + 1);
137+
next = edges[0][0];
138+
dfs(next, 0);
139+
vis.assign(vis.size(), false);
140+
dfs(next, 0);
141+
return ans;
142+
}
143+
144+
void dfs(int u, int t) {
145+
if (vis[u]) return;
146+
vis[u] = true;
147+
if (ans < t)
148+
{
149+
ans = t;
150+
next = u;
151+
}
152+
for (int v : g[u]) dfs(v, t + 1);
153+
}
154+
};
155+
```
57156
157+
### **Go**
158+
159+
```go
160+
func treeDiameter(edges [][]int) int {
161+
n := len(edges)
162+
g := make(map[int][]int)
163+
for _, e := range edges {
164+
g[e[0]] = append(g[e[0]], e[1])
165+
g[e[1]] = append(g[e[1]], e[0])
166+
}
167+
vis := make(map[int]bool, n+1)
168+
ans := 0
169+
next := edges[0][0]
170+
var dfs func(u, t int)
171+
dfs = func(u, t int) {
172+
if vis[u] {
173+
return
174+
}
175+
vis[u] = true
176+
if ans < t {
177+
ans = t
178+
next = u
179+
}
180+
if vs, ok := g[u]; ok {
181+
for _, v := range vs {
182+
dfs(v, t+1)
183+
}
184+
}
185+
}
186+
dfs(next, 0)
187+
vis = make(map[int]bool, n+1)
188+
dfs(next, 0)
189+
return ans
190+
}
58191
```
59192

60193
### **...**
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
class Solution {
2+
public:
3+
unordered_map<int, unordered_set<int>> g;
4+
vector<bool> vis;
5+
int ans;
6+
int next;
7+
8+
int treeDiameter(vector<vector<int>>& edges) {
9+
for (auto& e : edges)
10+
{
11+
g[e[0]].insert(e[1]);
12+
g[e[1]].insert(e[0]);
13+
}
14+
int n = edges.size();
15+
ans = 0;
16+
vis.resize(n + 1);
17+
next = edges[0][0];
18+
dfs(next, 0);
19+
vis.assign(vis.size(), false);
20+
dfs(next, 0);
21+
return ans;
22+
}
23+
24+
void dfs(int u, int t) {
25+
if (vis[u]) return;
26+
vis[u] = true;
27+
if (ans < t)
28+
{
29+
ans = t;
30+
next = u;
31+
}
32+
for (int v : g[u]) dfs(v, t + 1);
33+
}
34+
};
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
func treeDiameter(edges [][]int) int {
2+
n := len(edges)
3+
g := make(map[int][]int)
4+
for _, e := range edges {
5+
g[e[0]] = append(g[e[0]], e[1])
6+
g[e[1]] = append(g[e[1]], e[0])
7+
}
8+
vis := make(map[int]bool, n+1)
9+
ans := 0
10+
next := edges[0][0]
11+
var dfs func(u, t int)
12+
dfs = func(u, t int) {
13+
if vis[u] {
14+
return
15+
}
16+
vis[u] = true
17+
if ans < t {
18+
ans = t
19+
next = u
20+
}
21+
if vs, ok := g[u]; ok {
22+
for _, v := range vs {
23+
dfs(v, t+1)
24+
}
25+
}
26+
}
27+
dfs(next, 0)
28+
vis = make(map[int]bool, n+1)
29+
dfs(next, 0)
30+
return ans
31+
}

0 commit comments

Comments
 (0)