b_lc_陣列的最大公因數排序(並查集+質因數分解優化)
阿新 • • 發佈:2021-09-06
一個整數陣列 nums ,你可以在 nums 上執行下述操作 任意次 :
- 如果 gcd(nums[i], nums[j]) > 1 ,交換 nums[i] 和 nums[j] 的位置。其中 gcd(nums[i], nums[j]) 是 nums[i] 和 nums[j] 的最大公因數。
如果能使用上述交換方式將 nums 按 非遞減順序 排列,返回 true ;否則,返回 false 。
思路:如果兩層迴圈判斷是否可以和另一個數交換,然後加入到並查集的話會超時,這裡用質因數分解進行優化,直接將每個數的公因子加到並查集
class Solution { public: struct UF { int* fa; int* sz; UF(int N) { fa = new int[N + 5]; sz = new int[N + 5]; for (int i = 1; i <= N; i++) { fa[i] = i, sz[i] = 1; } } int find(int u) { return fa[u] == u ? u : fa[u] = find(fa[u]); } void merge(int u, int v) { int fu = find(u), fv = find(v); if (sz[fu] > sz[fv]) { fa[fv] = fu; // sz[fu] += sz[fv]; } else { fa[fu] = fv; // sz[fv] += sz[fu]; } } bool isConn(int u, int v) { return find(u) == find(v); } }; bool gcdSort(vector<int>& A) { int n = A.size(); UF* uf = new UF(3e5 + 5); vector<int> B = A; sort(B.begin(), B.end()); for (int x : A) { int t = x; for (int i = 2; i <= t / i; ++i) { bool find = false; while (t % i == 0) { t /= i; find = true; } if (find) { uf->merge(x, i); } } if (t > 1) { uf->merge(x, t); } } for (int i = 0; i < n; ++i) { if (A[i] != B[i]) { if (!uf->isConn(A[i], B[i])) { return false; } } } return true; } };