leetcode
leetcode 2401 ~ 2450
统计趣味子数组的数目

统计趣味子数组的数目

难度:

标签:

题目描述

You are given a 0-indexed integer array nums, an integer modulo, and an integer k.

Your task is to find the count of subarrays that are interesting.

A subarray nums[l..r] is interesting if the following condition holds:

  • Let cnt be the number of indices i in the range [l, r] such that nums[i] % modulo == k. Then, cnt % modulo == k.

Return an integer denoting the count of interesting subarrays.

Note: A subarray is a contiguous non-empty sequence of elements within an array.

 

Example 1:

Input: nums = [3,2,4], modulo = 2, k = 1
Output: 3
Explanation: In this example the interesting subarrays are: 
The subarray nums[0..0] which is [3]. 
- There is only one index, i = 0, in the range [0, 0] that satisfies nums[i] % modulo == k. 
- Hence, cnt = 1 and cnt % modulo == k.  
The subarray nums[0..1] which is [3,2].
- There is only one index, i = 0, in the range [0, 1] that satisfies nums[i] % modulo == k.  
- Hence, cnt = 1 and cnt % modulo == k.
The subarray nums[0..2] which is [3,2,4]. 
- There is only one index, i = 0, in the range [0, 2] that satisfies nums[i] % modulo == k. 
- Hence, cnt = 1 and cnt % modulo == k. 
It can be shown that there are no other interesting subarrays. So, the answer is 3.

Example 2:

Input: nums = [3,1,9,6], modulo = 3, k = 0
Output: 2
Explanation: In this example the interesting subarrays are: 
The subarray nums[0..3] which is [3,1,9,6]. 
- There are three indices, i = 0, 2, 3, in the range [0, 3] that satisfy nums[i] % modulo == k. 
- Hence, cnt = 3 and cnt % modulo == k. 
The subarray nums[1..1] which is [1]. 
- There is no index, i, in the range [1, 1] that satisfies nums[i] % modulo == k. 
- Hence, cnt = 0 and cnt % modulo == k. 
It can be shown that there are no other interesting subarrays. So, the answer is 2.

 

Constraints:

  • 1 <= nums.length <= 105
  • 1 <= nums[i] <= 109
  • 1 <= modulo <= 109
  • 0 <= k < modulo

代码结果

运行时间: 136 ms, 内存: 29.7 MB


// 思路:
// 1. 使用流处理来生成所有子数组。
// 2. 对每个子数组计算满足 nums[i] % modulo == k 的元素个数 cnt。
// 3. 通过流的 filter 操作过滤出 cnt % modulo == k 的子数组并统计其数量。

import java.util.stream.IntStream;

public class Solution {
    public long countInterestingSubarrays(int[] nums, int modulo, int k) {
        return IntStream.range(0, nums.length)
                .flatMap(start -> IntStream.range(start, nums.length)
                    .map(end -> (int) IntStream.range(start, end + 1)
                        .filter(i -> nums[i] % modulo == k)
                        .count()))
                .filter(cnt -> cnt % modulo == k)
                .count();
    }
}

解释

方法:

题解采用了前缀和和哈希表的思想。首先,遍历数组,计算出以每个元素为结尾的子数组中满足条件 nums[i] % modulo == k 的元素个数的累计和 temp。然后,计算出满足条件的子数组的个数。为了避免重复计算,使用哈希表 mp 来存储每个可能的累计和出现的次数。对于每个元素,我们计算出在当前累计和下,满足 cnt % modulo == k 的累计和 sl,然后将哈希表中对应 sl 的值累加到结果 res 中。最后,更新哈希表中当前累计和的计数。

时间复杂度:

O(n)

空间复杂度:

O(n)

代码细节讲解

🦆
在算法中,为什么使用前缀和的方法来统计满足条件的子数组,而不是直接枚举所有可能的子数组?
使用前缀和的方法可以有效减少重复计算,提高算法效率。如果直接枚举所有可能的子数组,复杂度会是 O(n^2),这在数据量大时会非常慢。而通过使用前缀和,结合哈希表,我们可以在 O(n) 时间内完成计算,这是因为我们可以通过前缀和快速计算任意子数组的和,而哈希表则用于快速查找满足特定条件的前缀和出现的次数。
🦆
哈希表中键值对的含义是什么?具体来说,哈希表中的键和值分别代表了什么?
在这个算法中,哈希表用于存储前缀和的模结果及其出现的次数。哈希表的键 'key' 表示从数组开始到当前位置的子数组的和对 modulo 的余数,而哈希表的值 'value' 表示这种特定的余数出现的次数。通过记录这些信息,我们可以快速查找到前面有多少个子数组的和满足特定条件,从而快速统计满足条件的子数组个数。
🦆
在更新哈希表 `mp[temp] += 1` 时,这一操作的目的是什么?
这一操作的目的是更新或记录当前前缀和模 modulo 的结果的出现次数。每遍历到一个新的元素,我们都会计算新的前缀和的模结果,然后在哈希表中增加这个模结果出现次数的记录。这样,当我们后面需要查找这个前缀和模结果出现的次数时,可以直接从哈希表中得到,从而快速计算出从当前位置向前有多少子数组的和满足特定条件。
🦆
如何理解计算 `sl = (temp - k + modulo) % modulo` 的逻辑?这一步骤是如何帮助我们找到满足条件的子数组的?
这一计算步骤是用来找出符合条件的前缀和的关键。在此算法中,我们需要找出满足 `(当前前缀和 - 某个早先前缀和) % modulo == k` 的子数组数目。通过 rearranging,我们可以得到 `当前前缀和 % modulo - k == 早先前缀和 % modulo`。因此,我们计算 `(temp - k + modulo) % modulo` 来得到应当与之前记录的前缀和模结果相等的值,这样我们就可以使用哈希表快速定位并计算满足条件的子数组的数量。

相关问题