69
69
70
70
### 方法一:两次 DFS
71
71
72
- 首先对任意一个结点做 DFS 求出最远的结点,然后以这个结点为根结点再做 DFS 到达另一个最远结点。第一次 DFS 到达的结点可以证明一定是这个图的直径的一端,第二次 DFS 就会达到另一端。下面来证明这个定理 。
72
+ 我们首先任选一个节点,从该节点开始进行深度优先搜索,找到距离该节点最远的节点,记为节点 $a$。然后从节点 $a$ 开始进行深度优先搜索,找到距离节点 $a$ 最远的节点,记为节点 $b$。可以证明,节点 $a$ 和节点 $b$ 之间的路径即为树的直径 。
73
73
74
- 定理:在一个连通无向无环图中,以任意结点出发所能到达的最远结点,一定是该图直径的端点之一。
75
-
76
- 证明:假设这条直径是 δ(s, t)。分两种情况:
77
-
78
- 1 . 当出发结点 y 在 δ(s, t) 时,假设到达的最远结点 z 不是 s, t 中的任一个。这时将 δ(y, z) 与不与之重合的 δ(y, s) 拼接(也可以假设不与之重合的是直径的另一个方向),可以得到一条更长的直径,与前提矛盾。
79
- 1 . 当出发结点 y 不在 δ(s, t) 上时,分两种情况:
80
-
81
- - 当 y 到达的最远结点 z 横穿 δ(s, t) 时,记与之相交的结点为 x。此时有 δ(y, z) = δ(y, x) + δ(x, z)。而此时 δ(y, z) > δ(y, t),故可得 δ(x, z) > δ(x, t)。由 1 的结论可知该假设不成立。
82
- - 当 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 这个直径对应的路外面。
83
-
84
- <img alt =" " src =" https://fastly.jsdelivr.net/gh/doocs/leetcode@main/solution/1200-1299/1245.Tree%20Diameter/images/tree-diameter.svg " >
85
-
86
- 因此定理成立。
74
+ 时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为节点数。
87
75
88
76
相似题目:
89
77
@@ -96,66 +84,56 @@ tags:
96
84
``` python
97
85
class Solution :
98
86
def treeDiameter (self , edges : List[List[int ]]) -> int :
99
- def dfs (u , t ):
100
- nonlocal ans, vis, d, next
101
- if vis[u]:
102
- return
103
- vis[u] = True
104
- for v in d[u]:
105
- dfs(v, t + 1 )
87
+ def dfs (i : int , fa : int , t : int ):
88
+ for j in g[i]:
89
+ if j != fa:
90
+ dfs(j, i, t + 1 )
91
+ nonlocal ans, a
106
92
if ans < t:
107
93
ans = t
108
- next = u
109
-
110
- d = defaultdict(set )
111
- vis = [False ] * (len (edges) + 1 )
112
- for u, v in edges:
113
- d[u].add(v)
114
- d[v].add(u)
115
- ans = 0
116
- next = 0
117
- dfs(edges[0 ][0 ], 0 )
118
- vis = [False ] * (len (edges) + 1 )
119
- dfs(next , 0 )
94
+ a = i
95
+
96
+ g = defaultdict(list )
97
+ for a, b in edges:
98
+ g[a].append(b)
99
+ g[b].append(a)
100
+ ans = a = 0
101
+ dfs(0 , - 1 , 0 )
102
+ dfs(a, - 1 , 0 )
120
103
return ans
121
104
```
122
105
123
106
#### Java
124
107
125
108
``` java
126
109
class Solution {
127
- private Map<Integer , Set<Integer > > g;
128
- private boolean [] vis;
129
- private int next;
110
+ private List<Integer > [] g;
130
111
private int ans;
112
+ private int a;
131
113
132
114
public int treeDiameter (int [][] edges ) {
133
- int n = edges. length;
134
- ans = 0 ;
135
- g = new HashMap<> ();
136
- for (int [] e : edges) {
137
- g. computeIfAbsent(e[0 ], k - > new HashSet<> ()). add(e[1 ]);
138
- g. computeIfAbsent(e[1 ], k - > new HashSet<> ()). add(e[0 ]);
115
+ int n = edges. length + 1 ;
116
+ g = new List [n];
117
+ Arrays . setAll(g, k - > new ArrayList<> ());
118
+ for (var e : edges) {
119
+ int a = e[0 ], b = e[1 ];
120
+ g[a]. add(b);
121
+ g[b]. add(a);
139
122
}
140
- vis = new boolean [n + 1 ];
141
- next = edges[0 ][0 ];
142
- dfs(next, 0 );
143
- vis = new boolean [n + 1 ];
144
- dfs(next, 0 );
123
+ dfs(0 , - 1 , 0 );
124
+ dfs(a, - 1 , 0 );
145
125
return ans;
146
126
}
147
127
148
- private void dfs (int u , int t ) {
149
- if (vis[u]) {
150
- return ;
128
+ private void dfs (int i , int fa , int t ) {
129
+ for (int j : g[i]) {
130
+ if (j != fa) {
131
+ dfs(j, i, t + 1 );
132
+ }
151
133
}
152
- vis[u] = true ;
153
134
if (ans < t) {
154
135
ans = t;
155
- next = u;
156
- }
157
- for (int v : g. get(u)) {
158
- dfs(v, t + 1 );
136
+ a = i;
159
137
}
160
138
}
161
139
}
@@ -166,71 +144,88 @@ class Solution {
166
144
``` cpp
167
145
class Solution {
168
146
public:
169
- unordered_map<int, unordered_set<int >> g;
170
- vector<bool > vis;
171
- int ans;
172
- int next;
173
-
174
147
int treeDiameter(vector<vector<int >>& edges) {
148
+ int n = edges.size() + 1;
149
+ vector<int > g[ n] ;
175
150
for (auto& e : edges) {
176
- g[e[0]].insert(e[1]);
177
- g[e[1]].insert(e[0]);
151
+ int a = e[ 0] , b = e[ 1] ;
152
+ g[ a] .push_back(b);
153
+ g[ b] .push_back(a);
178
154
}
179
- int n = edges.size();
180
- ans = 0 ;
181
- vis.resize(n + 1 );
182
- next = edges[0 ][0 ];
183
- dfs (next, 0);
184
- vis.assign(vis.size(), false);
185
- dfs(next, 0);
155
+ int ans = 0, a = 0;
156
+ auto dfs = [ &] (auto&& dfs, int i, int fa, int t) -> void {
157
+ for (int j : g[ i] ) {
158
+ if (j != fa) {
159
+ dfs(dfs, j, i, t + 1);
160
+ }
161
+ }
162
+ if (ans < t) {
163
+ ans = t;
164
+ a = i;
165
+ }
166
+ };
167
+ dfs(dfs, 0, -1, 0);
168
+ dfs(dfs, a, -1, 0);
186
169
return ans;
187
170
}
188
-
189
- void dfs(int u, int t) {
190
- if (vis[u]) return;
191
- vis[u] = true;
192
- if (ans < t) {
193
- ans = t;
194
- next = u;
195
- }
196
- for (int v : g[u]) dfs(v, t + 1);
197
- }
198
171
};
199
172
```
200
173
201
174
#### Go
202
175
203
176
```go
204
- func treeDiameter(edges [][]int) int {
205
- n := len(edges)
206
- g := make(map[int ][]int)
177
+ func treeDiameter(edges [][]int) (ans int) {
178
+ n := len(edges) + 1
179
+ g := make([ ][]int, n )
207
180
for _, e := range edges {
208
- g[e[0]] = append(g[e[0]], e[1])
209
- g[e[1]] = append(g[e[1]], e[0])
181
+ a, b := e[0], e[1]
182
+ g[a] = append(g[a], b)
183
+ g[b] = append(g[b], a)
210
184
}
211
- vis := make(map[int]bool, n+1)
212
- ans := 0
213
- next := edges[0][0]
214
- var dfs func(u, t int)
215
- dfs = func(u, t int) {
216
- if vis[u] {
217
- return
185
+ a := 0
186
+ var dfs func(i, fa, t int)
187
+ dfs = func(i, fa, t int) {
188
+ for _, j := range g[i] {
189
+ if j != fa {
190
+ dfs(j, i, t+1)
191
+ }
218
192
}
219
- vis[u] = true
220
193
if ans < t {
221
194
ans = t
222
- next = u
223
- }
224
- if vs, ok := g[u]; ok {
225
- for _, v := range vs {
226
- dfs(v, t+1)
227
- }
195
+ a = i
228
196
}
229
197
}
230
- dfs(next, 0)
231
- vis = make(map[int]bool, n+1)
232
- dfs(next, 0)
233
- return ans
198
+ dfs(0, -1, 0)
199
+ dfs(a, -1, 0)
200
+ return
201
+ }
202
+ ```
203
+
204
+ #### TypeScript
205
+
206
+ ``` ts
207
+ function treeDiameter(edges : number [][]): number {
208
+ const n = edges .length + 1 ;
209
+ const g: number [][] = Array .from ({ length: n }, () => []);
210
+ for (const [a, b] of edges ) {
211
+ g [a ].push (b );
212
+ g [b ].push (a );
213
+ }
214
+ let [ans, a] = [0 , 0 ];
215
+ const dfs = (i : number , fa : number , t : number ): void => {
216
+ for (const j of g [i ]) {
217
+ if (j !== fa ) {
218
+ dfs (j , i , t + 1 );
219
+ }
220
+ }
221
+ if (ans < t ) {
222
+ ans = t ;
223
+ a = i ;
224
+ }
225
+ };
226
+ dfs (0 , - 1 , 0 );
227
+ dfs (a , - 1 , 0 );
228
+ return ans ;
234
229
}
235
230
```
236
231
0 commit comments