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

Commit 1c9ce7c

Browse files
committed
feat: add solutions to lc problem: No.1998.GCD Sort of an Array
1 parent 6a04399 commit 1c9ce7c

File tree

6 files changed

+561
-3
lines changed

6 files changed

+561
-3
lines changed

‎solution/1900-1999/1998.GCD Sort of an Array/README.md‎

Lines changed: 234 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,27 +52,259 @@
5252
<li><code>2 &lt;= nums[i] &lt;= 10<sup>5</sup></code></li>
5353
</ul>
5454

55-
5655
## 解法
5756

5857
<!-- 这里可写通用的实现逻辑 -->
5958

59+
并查集。
60+
61+
并查集模板:
62+
63+
模板 1——朴素并查集:
64+
65+
```python
66+
# 初始化,p存储每个点的父节点
67+
p = list(range(n))
68+
69+
# 返回x的祖宗节点
70+
def find(x):
71+
if p[x] != x:
72+
# 路径压缩
73+
p[x] = find(p[x])
74+
return p[x]
75+
76+
# 合并a和b所在的两个集合
77+
p[find(a)] = find(b)
78+
```
79+
80+
模板 2——维护 size 的并查集:
81+
82+
```python
83+
# 初始化,p存储每个点的父节点,size只有当节点是祖宗节点时才有意义,表示祖宗节点所在集合中,点的数量
84+
p = list(range(n))
85+
size = [1] * n
86+
87+
# 返回x的祖宗节点
88+
def find(x):
89+
if p[x] != x:
90+
# 路径压缩
91+
p[x] = find(p[x])
92+
return p[x]
93+
94+
# 合并a和b所在的两个集合
95+
if find(a) != find(b):
96+
size[find(b)] += size[find(a)]
97+
p[find(a)] = find(b)
98+
```
99+
100+
模板 3——维护到祖宗节点距离的并查集:
101+
102+
```python
103+
# 初始化,p存储每个点的父节点,d[x]存储x到p[x]的距离
104+
p = list(range(n))
105+
d = [0] * n
106+
107+
# 返回x的祖宗节点
108+
def find(x):
109+
if p[x] != x:
110+
t = find(p[x])
111+
d[x] += d[p[x]]
112+
p[x] = t
113+
return p[x]
114+
115+
# 合并a和b所在的两个集合
116+
p[find(a)] = find(b)
117+
d[find(a)] = distance
118+
```
119+
120+
对于本题,最大公因数大于 1 的两个数,可以进行交换,因此,只要一个集合中所有数都存在相同公因数,那么这个集合中任意数都能进行两两交换,因此可以用并查集,把同个集合中的所有数字进行合并。
121+
122+
> 在这道题中,可以先预处理每个数的质因数,数字与质因数归属同一个集合。
123+
124+
合并之后,将原数组复制一份,并进行升序排列,得到新数组 s。然后遍历原数组,若原数组对应元素与新数组对应元素不相同,并且两个元素也不在同一个集合中,说明不满足条件,直接返回 false,否则遍历结束返回 true。
125+
60126
<!-- tabs:start -->
61127

62128
### **Python3**
63129

64130
<!-- 这里可写当前语言的特殊实现逻辑 -->
65131

66132
```python
67-
133+
class Solution:
134+
def gcdSort(self, nums: List[int]) -> bool:
135+
n = 10 ** 5 + 10
136+
p = list(range(n))
137+
f = collections.defaultdict(list)
138+
mx = max(nums)
139+
for i in range(2, mx + 1):
140+
if f[i]:
141+
continue
142+
for j in range(i, mx + 1, i):
143+
f[j].append(i)
144+
145+
def find(x):
146+
if p[x] != x:
147+
p[x] = find(p[x])
148+
return p[x]
149+
150+
for i in nums:
151+
for j in f[i]:
152+
p[find(i)] = find(j)
153+
154+
s = sorted(nums)
155+
for i, num in enumerate(nums):
156+
if s[i] != num and find(num) != find(s[i]):
157+
return False
158+
return True
68159
```
69160

70161
### **Java**
71162

72163
<!-- 这里可写当前语言的特殊实现逻辑 -->
73164

74165
```java
166+
class Solution {
167+
private int[] p;
168+
169+
public boolean gcdSort(int[] nums) {
170+
int n = 100010;
171+
p = new int[n];
172+
Map<Integer, List<Integer>> f = new HashMap<>();
173+
for (int i = 0; i < n; ++i) {
174+
p[i] = i;
175+
}
176+
int mx = 0;
177+
for (int num : nums) {
178+
mx = Math.max(mx, num);
179+
}
180+
for (int i = 2; i <= mx; ++i) {
181+
if (f.containsKey(i)) {
182+
continue;
183+
}
184+
for (int j = i; j <= mx; j += i) {
185+
f.putIfAbsent(j, new ArrayList<>());
186+
f.get(j).add(i);
187+
}
188+
}
189+
for (int i : nums) {
190+
for (int j : f.get(i)) {
191+
p[find(i)] = find(j);
192+
}
193+
}
194+
int[] s = new int[nums.length];
195+
System.arraycopy(nums, 0, s, 0, nums.length);
196+
Arrays.sort(s);
197+
for (int i = 0; i < nums.length; ++i) {
198+
if (s[i] != nums[i] && find(nums[i]) != find(s[i])) {
199+
return false;
200+
}
201+
}
202+
return true;
203+
}
204+
205+
int find(int x) {
206+
if (p[x] != x) {
207+
p[x] = find(p[x]);
208+
}
209+
return p[x];
210+
}
211+
}
212+
```
213+
214+
### **C++**
215+
216+
```cpp
217+
class Solution {
218+
public:
219+
vector<int> p;
220+
221+
bool gcdSort(vector<int>& nums) {
222+
int n = 100010;
223+
p.resize(n);
224+
for (int i = 0; i < n; ++i) p[i] = i;
225+
int mx = 0;
226+
for (auto num : nums) mx = max(mx, num);
227+
unordered_map<int, vector<int>> f;
228+
for (int i = 2; i <= mx; ++i)
229+
{
230+
if (!f[i].empty()) continue;
231+
for (int j = i; j <= mx; j += i) f[j].push_back(i);
232+
}
233+
for (int i : nums)
234+
{
235+
for (int j : f[i]) p[find(i)] = find(j);
236+
}
237+
vector<int> s = nums;
238+
sort(s.begin(), s.end());
239+
for (int i = 0; i < nums.size(); ++i)
240+
{
241+
if (s[i] != nums[i] && find(s[i]) != find(nums[i])) return false;
242+
}
243+
return true;
244+
}
245+
246+
int find(int x) {
247+
if (p[x] != x) p[x] = find(p[x]);
248+
return p[x];
249+
}
250+
};
251+
```
75252

253+
### **Go**
254+
255+
```go
256+
var p []int
257+
258+
func gcdSort(nums []int) bool {
259+
n := 100010
260+
p = make([]int, n)
261+
for i := 0; i < n; i++ {
262+
p[i] = i
263+
}
264+
mx := 0
265+
for _, num := range nums {
266+
mx = max(mx, num)
267+
}
268+
f := make([][]int, mx+1)
269+
for i := 2; i <= mx; i++ {
270+
if len(f[i]) > 0 {
271+
continue
272+
}
273+
for j := i; j <= mx; j += i {
274+
f[j] = append(f[j], i)
275+
}
276+
}
277+
for _, i := range nums {
278+
for _, j := range f[i] {
279+
p[find(i)] = find(j)
280+
}
281+
}
282+
s := make([]int, len(nums))
283+
for i, num := range nums {
284+
s[i] = num
285+
}
286+
sort.Ints(s)
287+
for i, num := range nums {
288+
if s[i] != num && find(s[i]) != find(num) {
289+
return false
290+
}
291+
}
292+
return true
293+
}
294+
295+
func find(x int) int {
296+
if p[x] != x {
297+
p[x] = find(p[x])
298+
}
299+
return p[x]
300+
}
301+
302+
func max(a, b int) int {
303+
if a > b {
304+
return a
305+
}
306+
return b
307+
}
76308
```
77309

78310
### **...**

0 commit comments

Comments
(0)

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