Skip to content

Commit d8117b5

Browse files
markdown style fix
1 parent 37e669f commit d8117b5

File tree

1 file changed

+43
-31
lines changed
  • solution/0952.Largest Component Size by Common Factor

1 file changed

+43
-31
lines changed

solution/0952.Largest Component Size by Common Factor/README.md

+43-31
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
# 952.按公因数计算最大组件大小
1+
## 按公因数计算最大组件大小
22

3-
## 题目描述
3+
### 问题描述
44

55
给定一个由不同正整数的组成的非空数组 `A`,考虑下面的图:
66

@@ -9,30 +9,47 @@
99

1010
返回图中最大连通组件的大小。
1111

12+
**示例1:**
1213

13-
14-
**示例 2:**
15-
14+
```
1615
输入:[4,6,15,35]
1716
输出:4
17+
```
18+
![示例1](/img/Largest-Component-Size-by-Common-Factor1.png)
1819

19-
![示例](https://assets.leetcode-cn.com/aliyun-lc-upload/uploads/2018/12/01/ex1.png)
20+
**示例2:**
2021

21-
**提示:**
22+
```
23+
输入: [20,50,9,63]
24+
输出: 2
25+
```
26+
![示例2](/img/Largest-Component-Size-by-Common-Factor2.png)
2227

23-
1. `1 <= A.length <= 20000`
24-
2. `1 <= A[i] <= 100000`
28+
**示例3**
2529

26-
## 解法
30+
```
31+
输入: [2,3,6,7,4,12,21,39]
32+
输出: 8
33+
```
2734

28-
### Naive 版本
35+
![示例3](/img/Largest-Component-Size-by-Common-Factor2.png)
36+
37+
**提示:**
38+
39+
* `1 <= A.length <= 20000`
40+
41+
* `1 <= A[i] <= 100000`
42+
43+
### 解法
44+
45+
#### Naive 版本
2946

3047
这道题涉及到画连线,应当涉及到 union-find。初步解法是:
3148

32-
* 使用数组,初始化各节点的 root 为自身,并且维护各节点 root 所连通的图的节点数量(size)为 1
33-
* 遍历数组中的每一个数,如果和其他数有大于 1 的公因数,则用 union 方法将他们连在一起
34-
* 在 union 的过程中,由于 union 的对象为各节点的根,因此需要使用 find 方法,并且缩短所涉及的节点和其根(root)的搜索距离,即将该节点与 root 直接连在一起。同时更新 size 数组的对应值
35-
* 在遍历结束后,遍历 size 数组,找到 size 最大的。
49+
- 使用数组,初始化各节点的 root 为自身,并且维护各节点 root 所连通的图的节点数量(size)为 1
50+
- 遍历数组中的每一个数,如果和其他数有大于 1 的公因数(也就是不互质),则用 union 方法将他们连在一起
51+
- 在 union 的过程中,由于 union 的对象为各节点的根,因此需要使用 find 方法,并且缩短所涉及的节点和其根(root)的搜索距离,即将该节点与 root 直接连在一起。同时更新 size 数组的对应值
52+
- 在遍历结束后,遍历 size 数组,找到 size 最大的。
3653

3754
```java
3855
class Solution {
@@ -111,25 +128,21 @@ class Solution {
111128
}
112129
```
113130

114-
但是这个代码其实会超时,因为中间的遍历逻辑会耗费很长的时间,时间复杂度为
115-
$$
116-
O(n^2)
117-
$$
118-
。因此我们需要更快一点的解法。
131+
但是这个代码其实会超时,因为中间的遍历逻辑会耗费很长的时间,时间复杂度为 O(n²)。因此我们需要更快一点的解法。
119132

120-
### 优化版本
133+
#### 优化版本
121134

122135
由于连通节点的条件是两个节点有公因数,那么他们可以通过这个公因数连在一起,而这个公因数又可以被分解为质因数,这样,我们只需要知道一个节点的质因数有哪些,并且将这些质因数和该节点相连。则对于每一个节点,我们都连接的是其质因数,或者说是质因数所对应的节点,但是本质上我们把这些有相同质因数的节点都连在了一起。具体步骤为:
123136

124-
* 维护 prime set,找到 100000 以内所有质数(找质数的方法应该都会吧)
125-
* 维护三个数组,分别为:
126-
* 各节点所连接的 root 编号,初始化为节点本身的编号
127-
* 各节点为 root 时,连通图的 size,初始化为 1
128-
* 各质数所连接到的节点对应的 root 的编号,初始化为 -1(因为开始时这些质数都没有和节点连在一起)
129-
* 遍历节点,其中遍历所有质数,如果节点可以整除质数,则将该质数所连通的节点(如果有的话)和当前节点连在一起;并且更新该质数连通 到 新的连通图的 root 的编号。同时更新 root 对应的 size
130-
* 遍历 size 数组,找到值最大的集合
137+
- 维护 prime set,找到 100000 以内所有质数(找质数的方法应该都会吧)
138+
- 维护三个数组,分别为:
139+
- 各节点所连接的 root 编号,初始化为节点本身的编号
140+
- 各节点为 root 时,连通图的 size,初始化为 1
141+
- 各质数所连接到的节点对应的 root 的编号,初始化为 -1(因为开始时这些质数都没有和节点连在一起)
142+
- 遍历节点,其中遍历所有质数,如果节点可以整除质数,则将该质数所连通的节点(如果有的话)和当前节点连在一起;并且更新该质数连通 到 新的连通图的 root 的编号。同时更新 root 对应的 size
143+
- 遍历 size 数组,找到值最大的集合
131144

132-
而题中给定了节点大小小于 100000,因此我们只需要找到 100000 里面的所有质数,并遍历节点将其连接到可以整除该节点的质数上,就等于是完成了有公因数之间的节点的连通。而根据我们上面的推算,遍历每个节点的所有质数时间复杂度是确定的为 O(np),p 为 100000 以内质数数量,即为 O(n),而 union-find 方法的每一个步骤 amortized 复杂度为 O(log*n),一个远小于 log n 的值。因此,我们通过优化了寻找连通边的方法,来达到优化算法的目的。
145+
而题中给定了节点值大小小于 100000,因此我们只需要找到 100000 里面的所有质数,并遍历节点将其连接到可以整除该节点的质数上,就等于是完成了有公因数之间的节点的连通。而根据我们上面的推算,遍历每个节点的所有质数时间复杂度是确定的为 O(np),p 为 100000 以内质数数量,即为 O(n),而 union-find 方法的每一个步骤 amortized 复杂度为 O(log*n),一个远小于 log n 的值。因此,我们通过优化了寻找连通边的方法,来达到优化算法的目的。
133146

134147
```java
135148
class Solution {
@@ -151,6 +164,7 @@ class Solution {
151164
// find all of its prime factors
152165
for (Integer prime: primes) {
153166
if (primes.contains(curr)) {
167+
// 如果 curr 本身就是质数,则比较简便。
154168
prime = curr;
155169
}
156170
if (curr % prime == 0) {
@@ -224,5 +238,3 @@ class Solution {
224238
}
225239
```
226240

227-
228-

0 commit comments

Comments
 (0)