Leetcode.2584 分割数组使乘积互质

题目链接

Leetcode.2584 分割数组使乘积互质 rating :2159

题目描述

给你一个长度为 n n n 的整数数组 n u m s nums nums,下标从 0 0 0 开始。

如果在下标 i i i分割 数组,其中 0 ≤ i ≤ n − 2 0 \leq i \leq n - 2 0in2 ,使前 i + 1 i + 1 i+1 个元素的乘积和剩余元素的乘积互质,则认为该分割 有效

  • 例如,如果 n u m s = [ 2 , 3 , 3 ] nums = [2, 3, 3] nums=[2,3,3] ,那么在下标 i = 0 i = 0 i=0 处的分割有效,因为 2 2 2 9 9 9 互质,而在下标 i = 1 i = 1 i=1 处的分割无效,因为 6 6 6 3 3 3 不互质。在下标 i = 2 i = 2 i=2 处的分割也无效,因为 i = n − 1 i = n - 1 i=n1

返回可以有效分割数组的最小下标 i i i ,如果不存在有效分割,则返回 − 1 -1 1

当且仅当 g c d ( v a l 1 , v a l 2 ) = 1 gcd(val_1, val_2) = 1 gcd(val1,val2)=1 成立时, v a l 1 val_1 val1 v a l 2 val_2 val2 这两个值才是互质的,其中 g c d ( v a l 1 , v a l 2 ) gcd(val_1, val_2) gcd(val1,val2) 表示 v a l 1 val1 val1 v a l 2 val2 val2最大公约数

示例 1:

在这里插入图片描述

输入:nums = [4,7,8,15,3,5]
输出:2
解释:上表展示了每个下标 i 处的前 i + 1 个元素的乘积、剩余元素的乘积和它们的最大公约数的值。
唯一一个有效分割位于下标 2 。
示例 2:

在这里插入图片描述

 输入:nums = [4,7,15,8,3,5]
输出:-1
解释:上表展示了每个下标 i 处的前 i + 1 个元素的乘积、剩余元素的乘积和它们的最大公约数的值。
不存在有效分割。
提示:
  • n = n u m s . l e n g t h n = nums.length n=nums.length
  • 1 ≤ n ≤ 1 0 4 1 \leq n \leq 10^4 1n104
  • 1 ≤ n u m s [ i ] ≤ 1 0 6 1 \leq nums[i] \leq 10^6 1nums[i]106

解法:质因数分解 + 哈希表

我们要使 v a l 1 和 v a l 2 val_1 和 val_2 val1val2 互质就是意味着 v a l 1 和 v a l 2 val_1 和 val_2 val1val2 分解质因数之后,它们各自的质因数之间没有交集,即没有相同的质因子。

我们先预处理出 1 0 6 10^6 106 范围内的质数,将其存入 p r i m e s primes primes 中,用 m i n _ f a c t o r [ x ] min\_factor[x] min_factor[x] 记录 x x x 的最小质因子;

然后我们用哈希表 s u m sum sum 记录整个数组的质因数的个数,比如质因数 p p p ,它的数量就是 s u m [ p ] sum[p] sum[p]

接着我们从 0 ≤ i < n − 1 0 \leq i < n - 1 0i<n1开始枚举每一个数组元素 n u m s [ i ] nums[i] nums[i],用哈希表 c n t cnt cnt 记录其质因数。

每当我们将一个元素 n u m s [ i ] nums[i] nums[i] 的质因数记录到 c n t cnt cnt 中,就开始判断( p p p n u m s [ i ] nums[i] nums[i] 的质因子):

  • 如果 c n t [ p ] = 0 cnt[p] = 0 cnt[p]=0,说明整个数组的质因子 p p p 都应该在 [ i + 1 , n − 1 ] [i+1,n-1] [i+1,n1]的范围内,当前 [ 0 , i ] [0,i] [0,i]不存在质因子 p p p,故 i i i 是一个有效分割;
  • 如果 c n t [ p ] = s u m [ p ] cnt[p] = sum[p] cnt[p]=sum[p],说明整个数组的质因子 p p p 都应该在 [ 0 , i ] [0,i] [0,i]的范围内, [ i + 1 , n − 1 ] [i+1,n-1] [i+1,n1]不存在质因子 p p p,故 i i i 是一个有效分割;
  • 如果 c n t [ p ] > 0   a n d   c n t [ p ] ≠ s u m [ p ] cnt[p] > 0 \ and\ cnt[p] \neq sum[p] cnt[p]>0 and cnt[p]=sum[p],说明整个数组的质因子 p p p i i i 的两侧,即 [ 0 , i ] [0,i] [0,i] [ i + 1 , n − 1 ] [i+1,n-1] [i+1,n1] 都存在,即当前 i i i 不是一个有效分割;

时间复杂度: O ( U + n l o g U ) O(U + nlogU) O(U+nlogU)

C++代码:

const int N = 1e6 + 10;
vector<int> primes;
int min_factor[N];

auto _ = []()
{
    vector<bool> st(N, true);
    for(int i = 2;i < N;i++)
    {
        if(st[i])
        {
            primes.push_back(i);
            min_factor[i] = i;
        }

        for(auto x:primes)
        {
            if(x * i >= N) break;
            st[i * x] = false;
            min_factor[i * x] = x;
            if(i % x == 0) break;
        }
    }

    return 0;
}();

class Solution {
public:
    int findValidSplit(vector<int>& nums) {
        int n = nums.size();
        unordered_map<int,int> sum, cnt;

        for(auto x:nums)
        {
            for(int i = x;i > 1;i /= min_factor[i])
            {
                sum[min_factor[i]]++;
            }
        }

        int mismatch = 0;
        auto fun = [&](int x)
        {
            int& k = cnt[x];
            if(k == 0)
            {
                if(++k != sum[x])
                {
                    mismatch++;
                }
            }
            else
            {
                if(++k == sum[x])
                {
                    mismatch--;
                }
            }

            return 0;
        };

        for(int i = 0;i < n - 1;i++)
        {
            auto x = nums[i];
            for(int j = x;j > 1;j /= min_factor[j])
            {
                fun(min_factor[j]);
            }

            if(mismatch == 0) return i;
        }

        return -1;
    }
};
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值