(nice!!!)LeetCode 1998. 数组的最大公因数排序(并查集、排序)

1998. 数组的最大公因数排序

在这里插入图片描述
在这里插入图片描述

思路:并查集。
1、可以交换的两个位置,一定是在同一个"最大公因数>1"的集合。即:a和b的最大公约数>1,b和c的最大公约数>1。那么a、b、c都是可以交换的。
2、如果两层循环来判断数组里的任意两个的最大公约数是否>1,那么时间复杂度0(n^2),超时了。这里可以对每个nums[i]进行质因数分解,然后将它和它的所有质因数都用并查集合并到一个集合。时间复杂度0(n*sqrt(n))。
3、解决了是否可以交换的问题,接着就是看数组交换后能否按“非递减顺序”排列。这里直接用新的数组nums1来复制一份数组nums,将nums进行排序,接着和nums1进行对比。相同的值直接继续,不同就看是否在一个集合里,不在就返回false。
细节看注释

class Solution {
const int N=1e5+10;
public:
    int p[100010];
    int findd(int u){
        if(p[u]!=u) p[u]=findd(p[u]);
        return p[u];
    }
    void merge(int a,int b){
        int ta=findd(a),tb=findd(b);
        if(ta!=tb) p[ta]=tb;
    }
    bool gcdSort(vector<int>& nums) {
    	//并查集
        for(int i=0;i<N;i++){
            p[i]=i;
        }
        //对每个nums[i]进行质因数分解
        for(int i=0;i<nums.size();i++){
            int t=nums[i];
            //将它和它的所有质因数都用并查集合并到一个集合
            for(int j=2;j<=t/j;j++){
                bool flag=0;
                while(t%j==0){
                    t/=j;
                    flag=1;
                }
                if(flag){
                    merge(nums[i],j);
                }
            }
            if(t>1){
                merge(nums[i],t);
            }
        }
        //用新的数组nums1来复制一份数组nums
        vector<int> nums1=nums;
        //将nums进行排序
        sort(nums.begin(),nums.end());
        bool flag=1;
        //接着和nums1进行对比
        for(int i=0;i<nums.size();i++){
        	//相同的值直接继续,不同就看是否在一个集合里
            if(nums[i]!=nums1[i]){
            	//不在就返回false
                if(findd(nums[i])!=findd(nums1[i])){
                    flag=0;
                    break;
                }
            }
        }
        return flag;
    }
};
  • 10
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值