Skip to content

Commit eb8b334

Browse files
committed
feat: add solutions for lc No.3873
1 parent d34338b commit eb8b334

7 files changed

Lines changed: 903 additions & 8 deletions

File tree

solution/3800-3899/3873.Maximum Points Activated with One Addition/README.md

Lines changed: 306 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -101,32 +101,334 @@ edit_url: https://github.com/doocs/leetcode/edit/main/solution/3800-3899/3873.Ma
101101

102102
<!-- solution:start -->
103103

104-
### 方法一
104+
### 方法一:并查集
105+
106+
我们可以使用并查集来解决这个问题。
107+
108+
首先,我们将所有点的 $x$ 坐标和 $y$ 坐标进行映射,使得它们在同一个并查集中。具体来说,我们可以将 $y$ 坐标加上一个足够大的常数 $m$(例如 $3 \times 10^9$),以确保 $x$ 和 $y$ 坐标不会发生冲突。
109+
110+
接下来,我们遍历所有点,将具有相同 $x$ 坐标或 $y$ 坐标的点进行合并。这样,具有相同 $x$ 或 $y$ 坐标的点就会被分到同一个集合中。
111+
112+
最后,我们统计每个集合中的点数,并找到最大的两个集合的大小。由于我们可以添加一个新的点来连接这两个集合,因此最终的答案就是这两个集合的大小之和再加上 1。
113+
114+
时间复杂度 $O(n \alpha(n))$,其中 $n$ 是点的数量,而 $\alpha$ 是阿克曼函数的反函数。空间复杂度 $O(n)$。
105115

106116
<!-- tabs:start -->
107117

108118
#### Python3
109119

110120
```python
111-
121+
class UnionFind:
122+
def __init__(self):
123+
self.p = {}
124+
self.size = {}
125+
126+
def find(self, x):
127+
if x not in self.p:
128+
self.p[x] = x
129+
self.size[x] = 1
130+
if self.p[x] != x:
131+
self.p[x] = self.find(self.p[x])
132+
return self.p[x]
133+
134+
def union(self, a, b):
135+
pa, pb = self.find(a), self.find(b)
136+
if pa == pb:
137+
return False
138+
if self.size[pa] > self.size[pb]:
139+
self.p[pb] = pa
140+
self.size[pa] += self.size[pb]
141+
else:
142+
self.p[pa] = pb
143+
self.size[pb] += self.size[pa]
144+
return True
145+
146+
147+
class Solution:
148+
def maxActivated(self, points: List[List[int]]) -> int:
149+
uf = UnionFind()
150+
m = int(3e9)
151+
152+
for x, y in points:
153+
uf.union(x, y + m)
154+
155+
cnt = Counter()
156+
for x, _ in points:
157+
cnt[uf.find(x)] += 1
158+
159+
mx1 = mx2 = 0
160+
for x in cnt.values():
161+
if mx1 < x:
162+
mx2 = mx1
163+
mx1 = x
164+
elif mx2 < x:
165+
mx2 = x
166+
return mx1 + mx2 + 1
112167
```
113168

114169
#### Java
115170

116171
```java
117-
172+
class UnionFind {
173+
Map<Long, Long> p = new HashMap<>();
174+
Map<Long, Integer> size = new HashMap<>();
175+
176+
long find(long x) {
177+
if (!p.containsKey(x)) {
178+
p.put(x, x);
179+
size.put(x, 1);
180+
}
181+
if (p.get(x) != x) {
182+
p.put(x, find(p.get(x)));
183+
}
184+
return p.get(x);
185+
}
186+
187+
boolean union(long a, long b) {
188+
long pa = find(a), pb = find(b);
189+
if (pa == pb) {
190+
return false;
191+
}
192+
193+
int sa = size.get(pa), sb = size.get(pb);
194+
if (sa > sb) {
195+
p.put(pb, pa);
196+
size.put(pa, sa + sb);
197+
} else {
198+
p.put(pa, pb);
199+
size.put(pb, sa + sb);
200+
}
201+
return true;
202+
}
203+
}
204+
205+
class Solution {
206+
public int maxActivated(int[][] points) {
207+
UnionFind uf = new UnionFind();
208+
long m = (long) 3e9;
209+
210+
for (int[] p : points) {
211+
uf.union(p[0], p[1] + m);
212+
}
213+
214+
Map<Long, Integer> cnt = new HashMap<>();
215+
for (int[] p : points) {
216+
cnt.merge(uf.find(p[0]), 1, Integer::sum);
217+
}
218+
219+
int mx1 = 0, mx2 = 0;
220+
for (int x : cnt.values()) {
221+
if (mx1 < x) {
222+
mx2 = mx1;
223+
mx1 = x;
224+
} else if (mx2 < x) {
225+
mx2 = x;
226+
}
227+
}
228+
229+
return mx1 + mx2 + 1;
230+
}
231+
}
118232
```
119233

120234
#### C++
121235

122236
```cpp
123-
237+
class UnionFind {
238+
public:
239+
unordered_map<long long, long long> p;
240+
unordered_map<long long, int> sz;
241+
242+
long long find(long long x) {
243+
if (!p.count(x)) {
244+
p[x] = x;
245+
sz[x] = 1;
246+
}
247+
if (p[x] != x) {
248+
p[x] = find(p[x]);
249+
}
250+
return p[x];
251+
}
252+
253+
bool unite(long long a, long long b) {
254+
long long pa = find(a), pb = find(b);
255+
if (pa == pb) return false;
256+
257+
if (sz[pa] > sz[pb]) {
258+
p[pb] = pa;
259+
sz[pa] += sz[pb];
260+
} else {
261+
p[pa] = pb;
262+
sz[pb] += sz[pa];
263+
}
264+
return true;
265+
}
266+
};
267+
268+
class Solution {
269+
public:
270+
int maxActivated(vector<vector<int>>& points) {
271+
UnionFind uf;
272+
long long m = (long long) 3e9;
273+
274+
for (auto& p : points) {
275+
uf.unite(p[0], p[1] + m);
276+
}
277+
278+
unordered_map<long long, int> cnt;
279+
for (auto& p : points) {
280+
long long root = uf.find(p[0]);
281+
cnt[root]++;
282+
}
283+
284+
int mx1 = 0, mx2 = 0;
285+
for (auto& [_, x] : cnt) {
286+
if (mx1 < x) {
287+
mx2 = mx1;
288+
mx1 = x;
289+
} else if (mx2 < x) {
290+
mx2 = x;
291+
}
292+
}
293+
294+
return mx1 + mx2 + 1;
295+
}
296+
};
124297
```
125298

126299
#### Go
127300

128301
```go
302+
type UnionFind struct {
303+
p map[int64]int64
304+
size map[int64]int
305+
}
306+
307+
func NewUnionFind() *UnionFind {
308+
return &UnionFind{
309+
p: map[int64]int64{},
310+
size: map[int64]int{},
311+
}
312+
}
313+
314+
func (uf *UnionFind) find(x int64) int64 {
315+
if _, ok := uf.p[x]; !ok {
316+
uf.p[x] = x
317+
uf.size[x] = 1
318+
}
319+
if uf.p[x] != x {
320+
uf.p[x] = uf.find(uf.p[x])
321+
}
322+
return uf.p[x]
323+
}
324+
325+
func (uf *UnionFind) union(a, b int64) bool {
326+
pa, pb := uf.find(a), uf.find(b)
327+
if pa == pb {
328+
return false
329+
}
330+
if uf.size[pa] > uf.size[pb] {
331+
uf.p[pb] = pa
332+
uf.size[pa] += uf.size[pb]
333+
} else {
334+
uf.p[pa] = pb
335+
uf.size[pb] += uf.size[pa]
336+
}
337+
return true
338+
}
339+
340+
func maxActivated(points [][]int) int {
341+
uf := NewUnionFind()
342+
m := int64(3e9)
343+
344+
for _, p := range points {
345+
uf.union(int64(p[0]), int64(p[1])+m)
346+
}
347+
348+
cnt := map[int64]int{}
349+
for _, p := range points {
350+
root := uf.find(int64(p[0]))
351+
cnt[root]++
352+
}
353+
354+
mx1, mx2 := 0, 0
355+
for _, x := range cnt {
356+
if mx1 < x {
357+
mx2 = mx1
358+
mx1 = x
359+
} else if mx2 < x {
360+
mx2 = x
361+
}
362+
}
363+
364+
return mx1 + mx2 + 1
365+
}
366+
```
129367

368+
#### TypeScript
369+
370+
```ts
371+
class UnionFind {
372+
p: Map<number, number> = new Map();
373+
size: Map<number, number> = new Map();
374+
375+
find(x: number): number {
376+
if (!this.p.has(x)) {
377+
this.p.set(x, x);
378+
this.size.set(x, 1);
379+
}
380+
if (this.p.get(x)! !== x) {
381+
this.p.set(x, this.find(this.p.get(x)!));
382+
}
383+
return this.p.get(x)!;
384+
}
385+
386+
union(a: number, b: number): boolean {
387+
const pa = this.find(a);
388+
const pb = this.find(b);
389+
if (pa === pb) return false;
390+
391+
const sa = this.size.get(pa)!;
392+
const sb = this.size.get(pb)!;
393+
394+
if (sa > sb) {
395+
this.p.set(pb, pa);
396+
this.size.set(pa, sa + sb);
397+
} else {
398+
this.p.set(pa, pb);
399+
this.size.set(pb, sa + sb);
400+
}
401+
return true;
402+
}
403+
}
404+
405+
function maxActivated(points: number[][]): number {
406+
const uf = new UnionFind();
407+
const m = 3e9;
408+
409+
for (const [x, y] of points) {
410+
uf.union(x, y + m);
411+
}
412+
413+
const cnt = new Map<number, number>();
414+
for (const [x] of points) {
415+
const root = uf.find(x);
416+
cnt.set(root, (cnt.get(root) ?? 0) + 1);
417+
}
418+
419+
let mx1 = 0,
420+
mx2 = 0;
421+
for (const x of cnt.values()) {
422+
if (mx1 < x) {
423+
mx2 = mx1;
424+
mx1 = x;
425+
} else if (mx2 < x) {
426+
mx2 = x;
427+
}
428+
}
429+
430+
return mx1 + mx2 + 1;
431+
}
130432
```
131433

132434
<!-- tabs:end -->

0 commit comments

Comments
 (0)