统计趣味子数组的数目

题目

给你一个下标从 0 开始的整数数组 nums ,以及整数 modulo 和整数 k 。

请你找出并统计数组中 趣味子数组 的数目。

如果 子数组 nums[l…r] 满足下述条件,则称其为 趣味子数组 :

在范围 [l, r] 内,设 cnt 为满足 nums[i] % modulo == k 的索引 i 的数量。并且 cnt % modulo == k 。
以整数形式表示并返回趣味子数组的数目。

注意:子数组是数组中的一个连续非空的元素序列。

样例

示例 1:
输入:nums = [3,2,4], modulo = 2, k = 1
输出:3
解释:在这个示例中,趣味子数组分别是: 
子数组 nums[0..0] ,也就是 [3] 。 
- 在范围 [0, 0] 内,只存在 1 个下标 i = 0 满足 nums[i] % modulo == k 。
- 因此 cnt = 1 ,且 cnt % modulo == k 。
子数组 nums[0..1] ,也就是 [3,2] 。
- 在范围 [0, 1] 内,只存在 1 个下标 i = 0 满足 nums[i] % modulo == k 。
- 因此 cnt = 1 ,且 cnt % modulo == k 。
子数组 nums[0..2] ,也就是 [3,2,4] 。
- 在范围 [0, 2] 内,只存在 1 个下标 i = 0 满足 nums[i] % modulo == k 。
- 因此 cnt = 1 ,且 cnt % modulo == k 。
可以证明不存在其他趣味子数组。因此,答案为 3 。

示例 2:
输入:nums = [3,1,9,6], modulo = 3, k = 0
输出:2
解释:在这个示例中,趣味子数组分别是: 
子数组 nums[0..3] ,也就是 [3,1,9,6] 。
- 在范围 [0, 3] 内,只存在 3 个下标 i = 0, 2, 3 满足 nums[i] % modulo == k 。
- 因此 cnt = 3 ,且 cnt % modulo == k 。
子数组 nums[1..1] ,也就是 [1] 。
- 在范围 [1, 1] 内,不存在下标满足 nums[i] % modulo == k 。
- 因此 cnt = 0 ,且 cnt % modulo == k 。
可以证明不存在其他趣味子数组,因此答案为 2

思路

因为本题 n u m s nums nums数组中的元素只与取模结果是否为 k k k有关,而与其本身的值无关,因此只需要对 n u m s nums nums的元素对 m o d u l o modulo modulo取模,判断结果是否为 k k k即可,如果为 k k k我们将其改为 1 1 1,反之改为 0 0 0,然后我们用前缀和得到 n u m s nums nums i i i个数中取模结果为 k k k的数的个数数组(即前缀和数组,记为 y y y数组)。假如 n u m s [ j . . . i ] nums[j...i] nums[j...i]中取模结果为 k k k的数的个数 c n t cnt cnt满足 c n t cnt cnt % m o d u l o = = k modulo==k modulo==k,对于前缀和数组 y y y即有 y [ i ] − y [ j − 1 ] y[i]-y[j-1] y[i]y[j1] % m o d u l o = = k modulo == k modulo==k,即有 y [ j − 1 ] = ( y [ i ] − k ) y[j-1]=(y[i]-k) y[j1]=(y[i]k) % m o d mod mod,因此用哈希表维护 y [ i ] y[i] y[i] % m o d mod mod的值的个数即可。

代码

class Solution {
public:
    long long countInterestingSubarrays(vector<int>& nums, int mod, int k) {
        int n=nums.size();
        vector<int>y(n+1);
        for(int i=0;i<n;i++){
            nums[i]=nums[i]%mod==k?1:0;
            y[i+1]=y[i]+nums[i];
        }
        map<int,long long>mp;
        mp[0]++;
        long long ans=0;
        for(int i=1;i<=n;i++){
            ans+=mp[((y[i]-k)%mod+mod)%mod];
            mp[y[i]%mod]++;
        }
        return ans;
    }
};
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值