diff --git a/solution/0600-0699/0684.Redundant Connection/README.md b/solution/0600-0699/0684.Redundant Connection/README.md index 0b7f73fb63d3b..211bf86a82ed4 100644 --- a/solution/0600-0699/0684.Redundant Connection/README.md +++ b/solution/0600-0699/0684.Redundant Connection/README.md @@ -65,7 +65,11 @@ tags: -### 方法一 +### 方法一:并查集 + +根据题意,我们需要找到一条可以删去的边,删除后剩余部分是一个有着 $n$ 个节点的树。我们可以遍历每一条边,判断这条边是否在同一个连通分量中。如果在同一个连通分量中,则说明这条边是多余的,可以删除,直接返回这条边即可。否则,我们将这条边所连接的两个节点合并到同一个连通分量中。 + +时间复杂度 $O(n \log n)$,空间复杂度 $O(n)$。其中 $n$ 为边的数量。 @@ -74,17 +78,17 @@ tags: ```python class Solution: def findRedundantConnection(self, edges: List[List[int]]) -> List[int]: - def find(x): + def find(x: int) -> int: if p[x] != x: p[x] = find(p[x]) return p[x] - p = list(range(1010)) + p = list(range(len(edges))) for a, b in edges: - if find(a) == find(b): + pa, pb = find(a - 1), find(b - 1) + if pa == pb: return [a, b] - p[find(a)] = find(b) - return [] + p[pa] = pb ``` #### Java @@ -94,18 +98,19 @@ class Solution { private int[] p; public int[] findRedundantConnection(int[][] edges) { - p = new int[1010]; - for (int i = 0; i < p.length; ++i) { + int n = edges.length; + p = new int[n]; + for (int i = 0; i < n; ++i) { p[i] = i; } - for (int[] e : edges) { - int a = e[0], b = e[1]; - if (find(a) == find(b)) { - return e; + for (int i = 0;; ++i) { + int pa = find(edges[i][0] - 1); + int pb = find(edges[i][1] - 1); + if (pa == pb) { + return edges[i]; } - p[find(a)] = find(b); + p[pa] = pb; } - return null; } private int find(int x) { @@ -122,22 +127,21 @@ class Solution { ```cpp class Solution { public: - vector p; - vector findRedundantConnection(vector>& edges) { - p.resize(1010); - for (int i = 0; i < p.size(); ++i) p[i] = i; - for (auto& e : edges) { - int a = e[0], b = e[1]; - if (find(a) == find(b)) return e; - p[find(a)] = find(b); + int n = edges.size(); + vector p(n); + iota(p.begin(), p.end(), 0); + function find = [&](int x) { + return x == p[x] ? x : p[x] = find(p[x]); + }; + for (int i = 0;; ++i) { + int pa = find(edges[i][0] - 1); + int pb = find(edges[i][1] - 1); + if (pa == pb) { + return edges[i]; + } + p[pa] = pb; } - return {}; - } - - int find(int x) { - if (p[x] != x) p[x] = find(p[x]); - return p[x]; } }; ``` @@ -146,25 +150,48 @@ public: ```go func findRedundantConnection(edges [][]int) []int { - p := make([]int, 1010) + n := len(edges) + p := make([]int, n) for i := range p { p[i] = i } - var find func(x int) int + var find func(int) int find = func(x int) int { if p[x] != x { p[x] = find(p[x]) } return p[x] } - for _, e := range edges { - a, b := e[0], e[1] - if find(a) == find(b) { - return e + for i := 0; ; i++ { + pa, pb := find(edges[i][0]-1), find(edges[i][1]-1) + if pa == pb { + return edges[i] } - p[find(a)] = find(b) + p[pa] = pb } - return []int{} +} +``` + +#### TypeScript + +```ts +function findRedundantConnection(edges: number[][]): number[] { + const n = edges.length; + const p: number[] = Array.from({ length: n }, (_, i) => i); + const find = (x: number): number => { + if (p[x] !== x) { + p[x] = find(p[x]); + } + return p[x]; + }; + for (let i = 0; ; ++i) { + const pa = find(edges[i][0] - 1); + const pb = find(edges[i][1] - 1); + if (pa === pb) { + return edges[i]; + } + p[pa] = pb; + } } ``` @@ -176,20 +203,313 @@ func findRedundantConnection(edges [][]int) []int { * @return {number[]} */ var findRedundantConnection = function (edges) { - let p = Array.from({ length: 1010 }, (_, i) => i); - function find(x) { + const n = edges.length; + const p = Array.from({ length: n }, (_, i) => i); + const find = x => { + if (p[x] !== x) { + p[x] = find(p[x]); + } + return p[x]; + }; + for (let i = 0; ; ++i) { + const pa = find(edges[i][0] - 1); + const pb = find(edges[i][1] - 1); + if (pa === pb) { + return edges[i]; + } + p[pa] = pb; + } +}; +``` + + + + + + + +### 方法二:并查集(模板做法) + +这里给出一个并查集的模板做法,供大家参考。 + +时间复杂度 $O(n \alpha(n))$,空间复杂度 $O(n)$。其中 $n$ 为边的数量,而 $\alpha(n)$ 是阿克曼函数的反函数,可以认为是一个很小的常数。 + + + +#### Python3 + +```python +class UnionFind: + __slots__ = "p", "size" + + def __init__(self, n: int): + self.p: List[int] = list(range(n)) + self.size: List[int] = [1] * n + + def find(self, x: int) -> int: + if self.p[x] != x: + self.p[x] = self.find(self.p[x]) + return self.p[x] + + def union(self, a: int, b: int) -> bool: + pa, pb = self.find(a), self.find(b) + if pa == pb: + return False + if self.size[pa] > self.size[pb]: + self.p[pb] = pa + self.size[pa] += self.size[pb] + else: + self.p[pa] = pb + self.size[pb] += self.size[pa] + return True + + +class Solution: + def findRedundantConnection(self, edges: List[List[int]]) -> List[int]: + uf = UnionFind(len(edges)) + for a, b in edges: + if not uf.union(a - 1, b - 1): + return [a, b] +``` + +#### Java + +```java +class UnionFind { + private final int[] p; + private final int[] size; + + public UnionFind(int n) { + p = new int[n]; + size = new int[n]; + for (int i = 0; i < n; ++i) { + p[i] = i; + size[i] = 1; + } + } + + public int find(int x) { if (p[x] != x) { p[x] = find(p[x]); } return p[x]; } - for (let [a, b] of edges) { - if (find(a) == find(b)) { - return [a, b]; + + public boolean union(int a, int b) { + int pa = find(a), pb = find(b); + if (pa == pb) { + return false; + } + if (size[pa] > size[pb]) { + p[pb] = pa; + size[pa] += size[pb]; + } else { + p[pa] = pb; + size[pb] += size[pa]; + } + return true; + } +} + +class Solution { + public int[] findRedundantConnection(int[][] edges) { + UnionFind uf = new UnionFind(edges.length); + for (int i = 0;; ++i) { + if (!uf.union(edges[i][0] - 1, edges[i][1] - 1)) { + return edges[i]; + } + } + } +} +``` + +#### C++ + +```cpp +class UnionFind { +public: + UnionFind(int n) { + p = vector(n); + size = vector(n, 1); + iota(p.begin(), p.end(), 0); + } + + bool unite(int a, int b) { + int pa = find(a), pb = find(b); + if (pa == pb) { + return false; + } + if (size[pa] > size[pb]) { + p[pb] = pa; + size[pa] += size[pb]; + } else { + p[pa] = pb; + size[pb] += size[pa]; + } + return true; + } + + int find(int x) { + if (p[x] != x) { + p[x] = find(p[x]); + } + return p[x]; + } + +private: + vector p, size; +}; + +class Solution { +public: + vector findRedundantConnection(vector>& edges) { + UnionFind uf(edges.size()); + for (int i = 0;; ++i) { + if (!uf.unite(edges[i][0] - 1, edges[i][1] - 1)) { + return edges[i]; + } + } + } +}; +``` + +#### Go + +```go +type unionFind struct { + p, size []int +} + +func newUnionFind(n int) *unionFind { + p := make([]int, n) + size := make([]int, n) + for i := range p { + p[i] = i + size[i] = 1 + } + return &unionFind{p, size} +} + +func (uf *unionFind) find(x int) int { + if uf.p[x] != x { + uf.p[x] = uf.find(uf.p[x]) + } + return uf.p[x] +} + +func (uf *unionFind) union(a, b int) bool { + pa, pb := uf.find(a), uf.find(b) + if pa == pb { + return false + } + if uf.size[pa] > uf.size[pb] { + uf.p[pb] = pa + uf.size[pa] += uf.size[pb] + } else { + uf.p[pa] = pb + uf.size[pb] += uf.size[pa] + } + return true +} + +func findRedundantConnection(edges [][]int) []int { + uf := newUnionFind(len(edges)) + for i := 0; ; i++ { + if !uf.union(edges[i][0]-1, edges[i][1]-1) { + return edges[i] + } + } +} +``` + +#### TypeScript + +```ts +class UnionFind { + p: number[]; + size: number[]; + constructor(n: number) { + this.p = Array.from({ length: n }, (_, i) => i); + this.size = Array(n).fill(1); + } + + find(x: number): number { + if (this.p[x] !== x) { + this.p[x] = this.find(this.p[x]); + } + return this.p[x]; + } + + union(a: number, b: number): boolean { + const [pa, pb] = [this.find(a), this.find(b)]; + if (pa === pb) { + return false; + } + if (this.size[pa] > this.size[pb]) { + this.p[pb] = pa; + this.size[pa] += this.size[pb]; + } else { + this.p[pa] = pb; + this.size[pb] += this.size[pa]; + } + return true; + } +} + +function findRedundantConnection(edges: number[][]): number[] { + const uf = new UnionFind(edges.length); + for (let i = 0; ; ++i) { + if (!uf.union(edges[i][0] - 1, edges[i][1] - 1)) { + return edges[i]; + } + } +} +``` + +#### JavaScript + +```js +class UnionFind { + constructor(n) { + this.p = Array.from({ length: n }, (_, i) => i); + this.size = Array(n).fill(1); + } + + find(x) { + if (this.p[x] !== x) { + this.p[x] = this.find(this.p[x]); + } + return this.p[x]; + } + + union(a, b) { + const pa = this.find(a); + const pb = this.find(b); + if (pa === pb) { + return false; + } + if (this.size[pa] > this.size[pb]) { + this.p[pb] = pa; + this.size[pa] += this.size[pb]; + } else { + this.p[pa] = pb; + this.size[pb] += this.size[pa]; + } + return true; + } +} + +/** + * @param {number[][]} edges + * @return {number[]} + */ +var findRedundantConnection = function (edges) { + const uf = new UnionFind(edges.length); + for (let i = 0; i < edges.length; i++) { + if (!uf.union(edges[i][0] - 1, edges[i][1] - 1)) { + return edges[i]; } - p[find(a)] = find(b); } - return []; }; ``` diff --git a/solution/0600-0699/0684.Redundant Connection/README_EN.md b/solution/0600-0699/0684.Redundant Connection/README_EN.md index be2170623ceb9..10bfad3f14072 100644 --- a/solution/0600-0699/0684.Redundant Connection/README_EN.md +++ b/solution/0600-0699/0684.Redundant Connection/README_EN.md @@ -59,7 +59,11 @@ tags: -### Solution 1 +### Solution 1: Union-Find + +According to the problem description, we need to find an edge that can be removed so that the remaining part is a tree with $n$ nodes. We can traverse each edge and determine whether the two nodes of this edge are in the same connected component. If they are in the same connected component, it means this edge is redundant and can be removed, so we directly return this edge. Otherwise, we merge the two nodes connected by this edge into the same connected component. + +The time complexity is $O(n \log n)$, and the space complexity is $O(n)$. Here, $n$ is the number of edges. @@ -68,17 +72,17 @@ tags: ```python class Solution: def findRedundantConnection(self, edges: List[List[int]]) -> List[int]: - def find(x): + def find(x: int) -> int: if p[x] != x: p[x] = find(p[x]) return p[x] - p = list(range(1010)) + p = list(range(len(edges))) for a, b in edges: - if find(a) == find(b): + pa, pb = find(a - 1), find(b - 1) + if pa == pb: return [a, b] - p[find(a)] = find(b) - return [] + p[pa] = pb ``` #### Java @@ -88,18 +92,19 @@ class Solution { private int[] p; public int[] findRedundantConnection(int[][] edges) { - p = new int[1010]; - for (int i = 0; i < p.length; ++i) { + int n = edges.length; + p = new int[n]; + for (int i = 0; i < n; ++i) { p[i] = i; } - for (int[] e : edges) { - int a = e[0], b = e[1]; - if (find(a) == find(b)) { - return e; + for (int i = 0;; ++i) { + int pa = find(edges[i][0] - 1); + int pb = find(edges[i][1] - 1); + if (pa == pb) { + return edges[i]; } - p[find(a)] = find(b); + p[pa] = pb; } - return null; } private int find(int x) { @@ -116,22 +121,21 @@ class Solution { ```cpp class Solution { public: - vector p; - vector findRedundantConnection(vector>& edges) { - p.resize(1010); - for (int i = 0; i < p.size(); ++i) p[i] = i; - for (auto& e : edges) { - int a = e[0], b = e[1]; - if (find(a) == find(b)) return e; - p[find(a)] = find(b); + int n = edges.size(); + vector p(n); + iota(p.begin(), p.end(), 0); + function find = [&](int x) { + return x == p[x] ? x : p[x] = find(p[x]); + }; + for (int i = 0;; ++i) { + int pa = find(edges[i][0] - 1); + int pb = find(edges[i][1] - 1); + if (pa == pb) { + return edges[i]; + } + p[pa] = pb; } - return {}; - } - - int find(int x) { - if (p[x] != x) p[x] = find(p[x]); - return p[x]; } }; ``` @@ -140,25 +144,48 @@ public: ```go func findRedundantConnection(edges [][]int) []int { - p := make([]int, 1010) + n := len(edges) + p := make([]int, n) for i := range p { p[i] = i } - var find func(x int) int + var find func(int) int find = func(x int) int { if p[x] != x { p[x] = find(p[x]) } return p[x] } - for _, e := range edges { - a, b := e[0], e[1] - if find(a) == find(b) { - return e + for i := 0; ; i++ { + pa, pb := find(edges[i][0]-1), find(edges[i][1]-1) + if pa == pb { + return edges[i] } - p[find(a)] = find(b) + p[pa] = pb } - return []int{} +} +``` + +#### TypeScript + +```ts +function findRedundantConnection(edges: number[][]): number[] { + const n = edges.length; + const p: number[] = Array.from({ length: n }, (_, i) => i); + const find = (x: number): number => { + if (p[x] !== x) { + p[x] = find(p[x]); + } + return p[x]; + }; + for (let i = 0; ; ++i) { + const pa = find(edges[i][0] - 1); + const pb = find(edges[i][1] - 1); + if (pa === pb) { + return edges[i]; + } + p[pa] = pb; + } } ``` @@ -170,20 +197,313 @@ func findRedundantConnection(edges [][]int) []int { * @return {number[]} */ var findRedundantConnection = function (edges) { - let p = Array.from({ length: 1010 }, (_, i) => i); - function find(x) { + const n = edges.length; + const p = Array.from({ length: n }, (_, i) => i); + const find = x => { + if (p[x] !== x) { + p[x] = find(p[x]); + } + return p[x]; + }; + for (let i = 0; ; ++i) { + const pa = find(edges[i][0] - 1); + const pb = find(edges[i][1] - 1); + if (pa === pb) { + return edges[i]; + } + p[pa] = pb; + } +}; +``` + + + + + + + +### Solution 2: Union-Find (Template Approach) + +Here is a template approach using Union-Find for your reference. + +The time complexity is $O(n \alpha(n))$, and the space complexity is $O(n)$. Here, $n$ is the number of edges, and $\alpha(n)$ is the inverse Ackermann function, which can be considered a very small constant. + + + +#### Python3 + +```python +class UnionFind: + __slots__ = "p", "size" + + def __init__(self, n: int): + self.p: List[int] = list(range(n)) + self.size: List[int] = [1] * n + + def find(self, x: int) -> int: + if self.p[x] != x: + self.p[x] = self.find(self.p[x]) + return self.p[x] + + def union(self, a: int, b: int) -> bool: + pa, pb = self.find(a), self.find(b) + if pa == pb: + return False + if self.size[pa] > self.size[pb]: + self.p[pb] = pa + self.size[pa] += self.size[pb] + else: + self.p[pa] = pb + self.size[pb] += self.size[pa] + return True + + +class Solution: + def findRedundantConnection(self, edges: List[List[int]]) -> List[int]: + uf = UnionFind(len(edges)) + for a, b in edges: + if not uf.union(a - 1, b - 1): + return [a, b] +``` + +#### Java + +```java +class UnionFind { + private final int[] p; + private final int[] size; + + public UnionFind(int n) { + p = new int[n]; + size = new int[n]; + for (int i = 0; i < n; ++i) { + p[i] = i; + size[i] = 1; + } + } + + public int find(int x) { if (p[x] != x) { p[x] = find(p[x]); } return p[x]; } - for (let [a, b] of edges) { - if (find(a) == find(b)) { - return [a, b]; + + public boolean union(int a, int b) { + int pa = find(a), pb = find(b); + if (pa == pb) { + return false; + } + if (size[pa] > size[pb]) { + p[pb] = pa; + size[pa] += size[pb]; + } else { + p[pa] = pb; + size[pb] += size[pa]; + } + return true; + } +} + +class Solution { + public int[] findRedundantConnection(int[][] edges) { + UnionFind uf = new UnionFind(edges.length); + for (int i = 0;; ++i) { + if (!uf.union(edges[i][0] - 1, edges[i][1] - 1)) { + return edges[i]; + } + } + } +} +``` + +#### C++ + +```cpp +class UnionFind { +public: + UnionFind(int n) { + p = vector(n); + size = vector(n, 1); + iota(p.begin(), p.end(), 0); + } + + bool unite(int a, int b) { + int pa = find(a), pb = find(b); + if (pa == pb) { + return false; + } + if (size[pa] > size[pb]) { + p[pb] = pa; + size[pa] += size[pb]; + } else { + p[pa] = pb; + size[pb] += size[pa]; + } + return true; + } + + int find(int x) { + if (p[x] != x) { + p[x] = find(p[x]); + } + return p[x]; + } + +private: + vector p, size; +}; + +class Solution { +public: + vector findRedundantConnection(vector>& edges) { + UnionFind uf(edges.size()); + for (int i = 0;; ++i) { + if (!uf.unite(edges[i][0] - 1, edges[i][1] - 1)) { + return edges[i]; + } + } + } +}; +``` + +#### Go + +```go +type unionFind struct { + p, size []int +} + +func newUnionFind(n int) *unionFind { + p := make([]int, n) + size := make([]int, n) + for i := range p { + p[i] = i + size[i] = 1 + } + return &unionFind{p, size} +} + +func (uf *unionFind) find(x int) int { + if uf.p[x] != x { + uf.p[x] = uf.find(uf.p[x]) + } + return uf.p[x] +} + +func (uf *unionFind) union(a, b int) bool { + pa, pb := uf.find(a), uf.find(b) + if pa == pb { + return false + } + if uf.size[pa] > uf.size[pb] { + uf.p[pb] = pa + uf.size[pa] += uf.size[pb] + } else { + uf.p[pa] = pb + uf.size[pb] += uf.size[pa] + } + return true +} + +func findRedundantConnection(edges [][]int) []int { + uf := newUnionFind(len(edges)) + for i := 0; ; i++ { + if !uf.union(edges[i][0]-1, edges[i][1]-1) { + return edges[i] + } + } +} +``` + +#### TypeScript + +```ts +class UnionFind { + p: number[]; + size: number[]; + constructor(n: number) { + this.p = Array.from({ length: n }, (_, i) => i); + this.size = Array(n).fill(1); + } + + find(x: number): number { + if (this.p[x] !== x) { + this.p[x] = this.find(this.p[x]); + } + return this.p[x]; + } + + union(a: number, b: number): boolean { + const [pa, pb] = [this.find(a), this.find(b)]; + if (pa === pb) { + return false; + } + if (this.size[pa] > this.size[pb]) { + this.p[pb] = pa; + this.size[pa] += this.size[pb]; + } else { + this.p[pa] = pb; + this.size[pb] += this.size[pa]; + } + return true; + } +} + +function findRedundantConnection(edges: number[][]): number[] { + const uf = new UnionFind(edges.length); + for (let i = 0; ; ++i) { + if (!uf.union(edges[i][0] - 1, edges[i][1] - 1)) { + return edges[i]; + } + } +} +``` + +#### JavaScript + +```js +class UnionFind { + constructor(n) { + this.p = Array.from({ length: n }, (_, i) => i); + this.size = Array(n).fill(1); + } + + find(x) { + if (this.p[x] !== x) { + this.p[x] = this.find(this.p[x]); + } + return this.p[x]; + } + + union(a, b) { + const pa = this.find(a); + const pb = this.find(b); + if (pa === pb) { + return false; + } + if (this.size[pa] > this.size[pb]) { + this.p[pb] = pa; + this.size[pa] += this.size[pb]; + } else { + this.p[pa] = pb; + this.size[pb] += this.size[pa]; + } + return true; + } +} + +/** + * @param {number[][]} edges + * @return {number[]} + */ +var findRedundantConnection = function (edges) { + const uf = new UnionFind(edges.length); + for (let i = 0; i < edges.length; i++) { + if (!uf.union(edges[i][0] - 1, edges[i][1] - 1)) { + return edges[i]; } - p[find(a)] = find(b); } - return []; }; ``` diff --git a/solution/0600-0699/0684.Redundant Connection/Solution.cpp b/solution/0600-0699/0684.Redundant Connection/Solution.cpp index d16769f3fec15..f82bc01858598 100644 --- a/solution/0600-0699/0684.Redundant Connection/Solution.cpp +++ b/solution/0600-0699/0684.Redundant Connection/Solution.cpp @@ -1,20 +1,19 @@ class Solution { public: - vector p; - vector findRedundantConnection(vector>& edges) { - p.resize(1010); - for (int i = 0; i < p.size(); ++i) p[i] = i; - for (auto& e : edges) { - int a = e[0], b = e[1]; - if (find(a) == find(b)) return e; - p[find(a)] = find(b); + int n = edges.size(); + vector p(n); + iota(p.begin(), p.end(), 0); + function find = [&](int x) { + return x == p[x] ? x : p[x] = find(p[x]); + }; + for (int i = 0;; ++i) { + int pa = find(edges[i][0] - 1); + int pb = find(edges[i][1] - 1); + if (pa == pb) { + return edges[i]; + } + p[pa] = pb; } - return {}; } - - int find(int x) { - if (p[x] != x) p[x] = find(p[x]); - return p[x]; - } -}; \ No newline at end of file +}; diff --git a/solution/0600-0699/0684.Redundant Connection/Solution.go b/solution/0600-0699/0684.Redundant Connection/Solution.go index 589430788445d..c44b876d86392 100644 --- a/solution/0600-0699/0684.Redundant Connection/Solution.go +++ b/solution/0600-0699/0684.Redundant Connection/Solution.go @@ -1,21 +1,21 @@ func findRedundantConnection(edges [][]int) []int { - p := make([]int, 1010) + n := len(edges) + p := make([]int, n) for i := range p { p[i] = i } - var find func(x int) int + var find func(int) int find = func(x int) int { if p[x] != x { p[x] = find(p[x]) } return p[x] } - for _, e := range edges { - a, b := e[0], e[1] - if find(a) == find(b) { - return e + for i := 0; ; i++ { + pa, pb := find(edges[i][0]-1), find(edges[i][1]-1) + if pa == pb { + return edges[i] } - p[find(a)] = find(b) + p[pa] = pb } - return []int{} -} \ No newline at end of file +} diff --git a/solution/0600-0699/0684.Redundant Connection/Solution.java b/solution/0600-0699/0684.Redundant Connection/Solution.java index 07bb29d36a69a..e28e96beb4641 100644 --- a/solution/0600-0699/0684.Redundant Connection/Solution.java +++ b/solution/0600-0699/0684.Redundant Connection/Solution.java @@ -2,18 +2,19 @@ class Solution { private int[] p; public int[] findRedundantConnection(int[][] edges) { - p = new int[1010]; - for (int i = 0; i < p.length; ++i) { + int n = edges.length; + p = new int[n]; + for (int i = 0; i < n; ++i) { p[i] = i; } - for (int[] e : edges) { - int a = e[0], b = e[1]; - if (find(a) == find(b)) { - return e; + for (int i = 0;; ++i) { + int pa = find(edges[i][0] - 1); + int pb = find(edges[i][1] - 1); + if (pa == pb) { + return edges[i]; } - p[find(a)] = find(b); + p[pa] = pb; } - return null; } private int find(int x) { @@ -22,4 +23,4 @@ private int find(int x) { } return p[x]; } -} \ No newline at end of file +} diff --git a/solution/0600-0699/0684.Redundant Connection/Solution.js b/solution/0600-0699/0684.Redundant Connection/Solution.js index be6e40d77ee60..35dec4256bd77 100644 --- a/solution/0600-0699/0684.Redundant Connection/Solution.js +++ b/solution/0600-0699/0684.Redundant Connection/Solution.js @@ -3,18 +3,20 @@ * @return {number[]} */ var findRedundantConnection = function (edges) { - let p = Array.from({ length: 1010 }, (_, i) => i); - function find(x) { - if (p[x] != x) { + const n = edges.length; + const p = Array.from({ length: n }, (_, i) => i); + const find = x => { + if (p[x] !== x) { p[x] = find(p[x]); } return p[x]; - } - for (let [a, b] of edges) { - if (find(a) == find(b)) { - return [a, b]; + }; + for (let i = 0; ; ++i) { + const pa = find(edges[i][0] - 1); + const pb = find(edges[i][1] - 1); + if (pa === pb) { + return edges[i]; } - p[find(a)] = find(b); + p[pa] = pb; } - return []; }; diff --git a/solution/0600-0699/0684.Redundant Connection/Solution.py b/solution/0600-0699/0684.Redundant Connection/Solution.py index 24d2baeb922b1..c5c3f31124cd5 100644 --- a/solution/0600-0699/0684.Redundant Connection/Solution.py +++ b/solution/0600-0699/0684.Redundant Connection/Solution.py @@ -1,13 +1,13 @@ class Solution: def findRedundantConnection(self, edges: List[List[int]]) -> List[int]: - def find(x): + def find(x: int) -> int: if p[x] != x: p[x] = find(p[x]) return p[x] - p = list(range(1010)) + p = list(range(len(edges))) for a, b in edges: - if find(a) == find(b): + pa, pb = find(a - 1), find(b - 1) + if pa == pb: return [a, b] - p[find(a)] = find(b) - return [] + p[pa] = pb diff --git a/solution/0600-0699/0684.Redundant Connection/Solution.ts b/solution/0600-0699/0684.Redundant Connection/Solution.ts new file mode 100644 index 0000000000000..93539dc45cba2 --- /dev/null +++ b/solution/0600-0699/0684.Redundant Connection/Solution.ts @@ -0,0 +1,18 @@ +function findRedundantConnection(edges: number[][]): number[] { + const n = edges.length; + const p: number[] = Array.from({ length: n }, (_, i) => i); + const find = (x: number): number => { + if (p[x] !== x) { + p[x] = find(p[x]); + } + return p[x]; + }; + for (let i = 0; ; ++i) { + const pa = find(edges[i][0] - 1); + const pb = find(edges[i][1] - 1); + if (pa === pb) { + return edges[i]; + } + p[pa] = pb; + } +} diff --git a/solution/0600-0699/0684.Redundant Connection/Solution2.cpp b/solution/0600-0699/0684.Redundant Connection/Solution2.cpp new file mode 100644 index 0000000000000..0ed94bf39ce89 --- /dev/null +++ b/solution/0600-0699/0684.Redundant Connection/Solution2.cpp @@ -0,0 +1,45 @@ +class UnionFind { +public: + UnionFind(int n) { + p = vector(n); + size = vector(n, 1); + iota(p.begin(), p.end(), 0); + } + + bool unite(int a, int b) { + int pa = find(a), pb = find(b); + if (pa == pb) { + return false; + } + if (size[pa] > size[pb]) { + p[pb] = pa; + size[pa] += size[pb]; + } else { + p[pa] = pb; + size[pb] += size[pa]; + } + return true; + } + + int find(int x) { + if (p[x] != x) { + p[x] = find(p[x]); + } + return p[x]; + } + +private: + vector p, size; +}; + +class Solution { +public: + vector findRedundantConnection(vector>& edges) { + UnionFind uf(edges.size()); + for (int i = 0;; ++i) { + if (!uf.unite(edges[i][0] - 1, edges[i][1] - 1)) { + return edges[i]; + } + } + } +}; diff --git a/solution/0600-0699/0684.Redundant Connection/Solution2.go b/solution/0600-0699/0684.Redundant Connection/Solution2.go new file mode 100644 index 0000000000000..2e27fed96fbfe --- /dev/null +++ b/solution/0600-0699/0684.Redundant Connection/Solution2.go @@ -0,0 +1,44 @@ +type unionFind struct { + p, size []int +} + +func newUnionFind(n int) *unionFind { + p := make([]int, n) + size := make([]int, n) + for i := range p { + p[i] = i + size[i] = 1 + } + return &unionFind{p, size} +} + +func (uf *unionFind) find(x int) int { + if uf.p[x] != x { + uf.p[x] = uf.find(uf.p[x]) + } + return uf.p[x] +} + +func (uf *unionFind) union(a, b int) bool { + pa, pb := uf.find(a), uf.find(b) + if pa == pb { + return false + } + if uf.size[pa] > uf.size[pb] { + uf.p[pb] = pa + uf.size[pa] += uf.size[pb] + } else { + uf.p[pa] = pb + uf.size[pb] += uf.size[pa] + } + return true +} + +func findRedundantConnection(edges [][]int) []int { + uf := newUnionFind(len(edges)) + for i := 0; ; i++ { + if !uf.union(edges[i][0]-1, edges[i][1]-1) { + return edges[i] + } + } +} diff --git a/solution/0600-0699/0684.Redundant Connection/Solution2.java b/solution/0600-0699/0684.Redundant Connection/Solution2.java new file mode 100644 index 0000000000000..c350d06e3d2b5 --- /dev/null +++ b/solution/0600-0699/0684.Redundant Connection/Solution2.java @@ -0,0 +1,46 @@ +class UnionFind { + private final int[] p; + private final int[] size; + + public UnionFind(int n) { + p = new int[n]; + size = new int[n]; + for (int i = 0; i < n; ++i) { + p[i] = i; + size[i] = 1; + } + } + + public int find(int x) { + if (p[x] != x) { + p[x] = find(p[x]); + } + return p[x]; + } + + public boolean union(int a, int b) { + int pa = find(a), pb = find(b); + if (pa == pb) { + return false; + } + if (size[pa] > size[pb]) { + p[pb] = pa; + size[pa] += size[pb]; + } else { + p[pa] = pb; + size[pb] += size[pa]; + } + return true; + } +} + +class Solution { + public int[] findRedundantConnection(int[][] edges) { + UnionFind uf = new UnionFind(edges.length); + for (int i = 0;; ++i) { + if (!uf.union(edges[i][0] - 1, edges[i][1] - 1)) { + return edges[i]; + } + } + } +} diff --git a/solution/0600-0699/0684.Redundant Connection/Solution2.js b/solution/0600-0699/0684.Redundant Connection/Solution2.js new file mode 100644 index 0000000000000..c46c247afb4d2 --- /dev/null +++ b/solution/0600-0699/0684.Redundant Connection/Solution2.js @@ -0,0 +1,42 @@ +class UnionFind { + constructor(n) { + this.p = Array.from({ length: n }, (_, i) => i); + this.size = Array(n).fill(1); + } + + find(x) { + if (this.p[x] !== x) { + this.p[x] = this.find(this.p[x]); + } + return this.p[x]; + } + + union(a, b) { + const pa = this.find(a); + const pb = this.find(b); + if (pa === pb) { + return false; + } + if (this.size[pa] > this.size[pb]) { + this.p[pb] = pa; + this.size[pa] += this.size[pb]; + } else { + this.p[pa] = pb; + this.size[pb] += this.size[pa]; + } + return true; + } +} + +/** + * @param {number[][]} edges + * @return {number[]} + */ +var findRedundantConnection = function (edges) { + const uf = new UnionFind(edges.length); + for (let i = 0; i < edges.length; i++) { + if (!uf.union(edges[i][0] - 1, edges[i][1] - 1)) { + return edges[i]; + } + } +}; diff --git a/solution/0600-0699/0684.Redundant Connection/Solution2.py b/solution/0600-0699/0684.Redundant Connection/Solution2.py new file mode 100644 index 0000000000000..43195e09b70d0 --- /dev/null +++ b/solution/0600-0699/0684.Redundant Connection/Solution2.py @@ -0,0 +1,31 @@ +class UnionFind: + __slots__ = "p", "size" + + def __init__(self, n: int): + self.p: List[int] = list(range(n)) + self.size: List[int] = [1] * n + + def find(self, x: int) -> int: + if self.p[x] != x: + self.p[x] = self.find(self.p[x]) + return self.p[x] + + def union(self, a: int, b: int) -> bool: + pa, pb = self.find(a), self.find(b) + if pa == pb: + return False + if self.size[pa] > self.size[pb]: + self.p[pb] = pa + self.size[pa] += self.size[pb] + else: + self.p[pa] = pb + self.size[pb] += self.size[pa] + return True + + +class Solution: + def findRedundantConnection(self, edges: List[List[int]]) -> List[int]: + uf = UnionFind(len(edges)) + for a, b in edges: + if not uf.union(a - 1, b - 1): + return [a, b] diff --git a/solution/0600-0699/0684.Redundant Connection/Solution2.ts b/solution/0600-0699/0684.Redundant Connection/Solution2.ts new file mode 100644 index 0000000000000..37ca241984721 --- /dev/null +++ b/solution/0600-0699/0684.Redundant Connection/Solution2.ts @@ -0,0 +1,39 @@ +class UnionFind { + p: number[]; + size: number[]; + constructor(n: number) { + this.p = Array.from({ length: n }, (_, i) => i); + this.size = Array(n).fill(1); + } + + find(x: number): number { + if (this.p[x] !== x) { + this.p[x] = this.find(this.p[x]); + } + return this.p[x]; + } + + union(a: number, b: number): boolean { + const [pa, pb] = [this.find(a), this.find(b)]; + if (pa === pb) { + return false; + } + if (this.size[pa] > this.size[pb]) { + this.p[pb] = pa; + this.size[pa] += this.size[pb]; + } else { + this.p[pa] = pb; + this.size[pb] += this.size[pa]; + } + return true; + } +} + +function findRedundantConnection(edges: number[][]): number[] { + const uf = new UnionFind(edges.length); + for (let i = 0; ; ++i) { + if (!uf.union(edges[i][0] - 1, edges[i][1] - 1)) { + return edges[i]; + } + } +} diff --git a/solution/1200-1299/1258.Synonymous Sentences/Solution.java b/solution/1200-1299/1258.Synonymous Sentences/Solution.java index 2890205e8c780..392bc39b73869 100644 --- a/solution/1200-1299/1258.Synonymous Sentences/Solution.java +++ b/solution/1200-1299/1258.Synonymous Sentences/Solution.java @@ -37,7 +37,7 @@ class Solution { private List t = new ArrayList<>(); private List words; private Map d; - private UnionFind uf; + private Solution2 uf; private List[] g; private String[] sentence; @@ -52,7 +52,7 @@ public List generateSentences(List> synonyms, String text) for (int i = 0; i < words.size(); ++i) { d.put(words.get(i), i); } - uf = new UnionFind(n); + uf = new Solution2(n); for (List pairs : synonyms) { uf.union(d.get(pairs.get(0)), d.get(pairs.get(1))); } @@ -86,4 +86,4 @@ private void dfs(int i) { } } } -} \ No newline at end of file +}