给你一个整数数组 nums ,你可以在 nums 上执行下述操作 任意次 :
如果 gcd(nums[i], nums[j]) > 1 ,交换 nums[i] 和 nums[j] 的位置。其中 gcd(nums[i], nums[j]) 是 nums[i] 和 nums[j] 的最大公因数。
如果能使用上述交换方式将 nums 按 非递减顺序 排列,返回 true ;否则,返回 false 。
示例 1:
输入:nums = [7,21,3]
输出:true
解释:可以执行下述操作完成对 [7,21,3] 的排序:
- 交换 7 和 21 因为 gcd(7,21) = 7 。nums = [21,7,3]
- 交换 21 和 3 因为 gcd(21,3) = 3 。nums = [3,7,21]
示例 2:
输入:nums = [5,2,6,2]
输出:false
解释:无法完成排序,因为 5 不能与其他元素交换。
示例 3:
输入:nums = [10,5,9,3,15]
输出:true
解释:
可以执行下述操作完成对 [10,5,9,3,15] 的排序:
- 交换 10 和 15 因为 gcd(10,15) = 5 。nums = [15,5,9,3,10]
- 交换 15 和 3 因为 gcd(15,3) = 3 。nums = [3,5,9,15,10]
- 交换 10 和 15 因为 gcd(10,15) = 5 。nums = [3,5,9,10,15]
java代码:
class UnionFind
{
int [] parent;
int [] size;
UnionFind(int n)
{
parent = new int [n];
size = new int [n];
for (int x = 0; x < n; x ++)
parent[x] = x;
Arrays.fill(size, 1);
}
public int Find(int x)
{
if (parent[x] != x)
parent[x] = Find(parent[x]);
return parent[x];
}
public boolean Union(int x, int y)
{
int root_x = Find(x);
int root_y = Find(y);
if (root_x == root_y)
return false;
if (size[root_x] > size[root_y])
{
int tmp = root_x;
root_x = root_y;
root_y = tmp;
}
parent[root_x] = root_y;
size[root_y] += size[root_x];
return true;
}
public boolean connected(int x, int y)
{
return Find(x) == Find(y);
}
}
class Solution
{
public boolean gcdSort(int[] nums)
{
int N = 100010;
UnionFind UF = new UnionFind(N);
int n = nums.length;
for (int x : nums)
{
int a = 2;
while (a * a <= x)
{
if (x % a == 0)
{
int b = x / a;
UF.Union(x, a);
UF.Union(x, b);
}
a ++;
}
}
int [] tar = Arrays.copyOfRange(nums, 0, n);
Arrays.sort(tar);
for (int i = 0; i < n; i ++)
{
int x = nums[i];
int y = tar[i];
if (UF.connected(x, y) == false)
return false;
}
return true;
}
}
















