Split the Array to Make Coprime Products

Questions:

请添加图片描述

请添加图片描述

思路:

这个题挺有意思的, 首先肯定不能真的做prefixProduct, nums[I] 的上限是10^6, 乘几个估计就爆了. 那么我们做题的角度就应该从每个数字的质数分解看. 其实这个题是可以大胆的给每个数字做质因数分解的. 不用担心, 因为最大就是10^6, 所以我们只要让每个nums对从i = 2 ~1000 的数字做除法, 就能得到质因数分解. 然后worst case, 假设一个数字, 她最坏的情况就是一直除以2. 这样的话每个nums 最久是处理O(log(1000000)) = 13. 也是很小的数字. 然后n <= 10000. 所以完完全全 对n个nums做质因数分解的time complexity是非常小的. 可以放心做.

然后那么如果可以做质因数分解, 那就把所有的prime factor都拿到然后存起来. 存在一个HashMap里.
接着我们要做的时候就是有点儿技巧了.
我们假设我们已经存好了n个nums所有的prime factor 在suffixProduct里
然后我们再创建一个prefixProduct, 从头开始再count 所有的质因数

看到这儿可能会有些迷糊, 这怎么判断coprime呢.
仔细想想: 我们判断两个数字是不是coprime, 怎么判断?
两个数字完全没有common 的 质因子.
那么, 我创建了另一个prefixProduct之后怎么帮助判断suffix和prefix有没有common prime factor呢?

我们的prefixProduct, 当从左到右重新存储prime factor number的时候.如果当有一个prime factor的数量增加到=suffixProduct里这个prime factor的数量时, 是不是就相当于. 在这个位置往后面的product 都不再出现这个prime factor了.
那也就是说这个prime factor是目前这个prefix product这儿unique的. suffix没有.
同理如果所有的prefixProduct里存储的 prime factor的数量 都等于suffixProduct 里对应prime factor的数量时, 就代表这些prime factor 所有的, 都只存在于当前这个index, 的prefix上. 那么我们就能确定在这个index. prefix和suffix是 coprime…

class Solution {
    public int findValidSplit(int[] nums) {
        Map<Integer, Integer> suffixProduct = new HashMap<>();
        Map<Integer, Integer> prefixProduct = new HashMap<>();
        
        for(int n: nums){
            for(int factor: factorize(n)){
                suffixProduct.put(factor, suffixProduct.getOrDefault(factor, 0)+1);
            }
        }
        
        int common = 0;
        for(int i = 0;i < nums.length-1; ++i){
            for(int factor: factorize(nums[i])){
                prefixProduct.put(factor, prefixProduct.getOrDefault(factor, 0)+1);
                if(prefixProduct.get(factor) == 1) common++;
                // means this is unique divisor in prefixproduct
                // has to use .equals() if we are comparing two Integer
                if(prefixProduct.get(factor).equals(suffixProduct.get(factor))) common--;
            }
            
            if(common == 0) return i;
        }
        
        return -1;
    }
    
    
    List<Integer> factorize(int n){
        List<Integer> res = new ArrayList<>();
        // since nums[i] <= 1000000, so we only iterate to 1000
        for(int i = 2; i <= 1000; i += (i%2 == 0? 1: 2)){
            if(n % i == 0) res.add(i);
            while(n % i == 0){
                n = n/i;
            }
            if(n == 1) break;
        }
        
        if(n > 1) res.add(n);
        return res;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值