Leetcode 3729. Count Distinct Subarrays Divisible by K in Sorted Array
- Leetcode 3729. Count Distinct Subarrays Divisible by K in Sorted Array
- 1. 解题思路
- 2. 代码实现
- 题目链接:3729. Count Distinct Subarrays Divisible by K in Sorted Array
1. 解题思路
对这一题而言,如果不用考虑去重,那么显然我们只需要求出给定数组的前序和数组,然后将其元素按照其对kkk的余数进行统计,那么对于其答案就是:
answer=∑i=0kci∗(ci−1)2answer = \sum\limits_{i=0}^{k} \frac{c_i * (c_i-1)}{2}answer=i=0∑k2ci∗(ci−1)
其中,cic_ici表示余数为iii时的前序和的个数。
但是这里会有重复的情况,因此,我们需要去除掉这里多算的所有重复情况的个数。由于题目中已知数组是非递减的,因此,如果满足有两个子数组(ni⋯nj)(n_i \cdots n_j)(ni⋯nj)与(nl⋯nr)(n_l \cdots n_r)(nl⋯nr)完全相同,那么必有这些数的元素必然完全相同。
因此,我们只需要找出所有连续的相同元素的子串,考虑其中会产生多少个重复计算的数组个数即可。而要使得若干个相同元素的和被kkk整除,那么其连续的个数必然为kkk与kkk和该元素的最大公约数的除数的倍数。而其被多记的次数就是该数组的长度减去对应的倍数的个数。
2. 代码实现
我们将其翻译为python代码语言就是:
class Solution:def numGoodSubarrays(self, nums: List[int], k: int) -> int:n = len(nums)cumsum = list(accumulate(nums, initial=0))reminders = [x%k for x in cumsum]cnt = Counter(reminders)ans = sum(x * (x-1) // 2 for x in cnt.values())idx = 0while idx < n:rb = bisect.bisect_right(nums, nums[idx])m = rb - idxif k == 1:ans -= m * (m+1) // 2 - melse:l = k // gcd(k, nums[idx])for i in range(l, m, l):ans -= m-iidx = rbreturn ans
提交代码评测得到:耗时311ms,占用内存41.28MB。
