Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

add solution 0952 #132

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
yanglbme merged 8 commits into doocs:master from biubiubiubiubiubiubiu:master
Dec 15, 2018
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
markdown style fix
  • Loading branch information
commit d8117b5851fa157a0654cab06e5fb24fba5fd039
74 changes: 43 additions & 31 deletions solution/0952.Largest Component Size by Common Factor/README.md
View file Open in desktop
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# 952.按公因数计算最大组件大小
## 按公因数计算最大组件大小

## 题目描述
### 问题描述

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

Expand All @@ -9,30 +9,47 @@

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

**示例1:**


**示例 2:**

```
输入:[4,6,15,35]
输出:4
```
![示例1](/img/Largest-Component-Size-by-Common-Factor1.png)

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

**提示:**
```
输入: [20,50,9,63]
输出: 2
```
![示例2](/img/Largest-Component-Size-by-Common-Factor2.png)

1. `1 <= A.length <= 20000`
2. `1 <= A[i] <= 100000`
**示例3**

## 解法
```
输入: [2,3,6,7,4,12,21,39]
输出: 8
```

### Naive 版本
![示例3](/img/Largest-Component-Size-by-Common-Factor2.png)

**提示:**

* `1 <= A.length <= 20000`

* `1 <= A[i] <= 100000`

### 解法

#### Naive 版本

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

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

```java
class Solution {
Expand Down Expand Up @@ -111,25 +128,21 @@ class Solution {
}
```

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

### 优化版本
#### 优化版本

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

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

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

```java
class Solution {
Expand All @@ -151,6 +164,7 @@ class Solution {
// find all of its prime factors
for (Integer prime: primes) {
if (primes.contains(curr)) {
// 如果 curr 本身就是质数,则比较简便。
prime = curr;
}
if (curr % prime == 0) {
Expand Down Expand Up @@ -224,5 +238,3 @@ class Solution {
}
```



AltStyle によって変換されたページ (->オリジナル) /