Leetcode 3729. Count Distinct Subarrays Divisible by K in Sorted Array

  • [Leetcode 3729. Count Distinct Subarrays Divisible by K in Sorted Array](#Leetcode 3729. Count Distinct Subarrays Divisible by K in Sorted Array)
    • [1. 解题思路](#1. 解题思路)
    • [2. 代码实现](#2. 代码实现)

1. 解题思路

对这一题而言,如果不用考虑去重,那么显然我们只需要求出给定数组的前序和数组,然后将其元素按照其对 k k k的余数进行统计,那么对于其答案就是:
a n s w e r = ∑ i = 0 k c i ∗ ( c i − 1 ) 2 answer = \sum\limits_{i=0}^{k} \frac{c_i * (c_i-1)}{2} answer=i=0∑k2ci∗(ci−1)

其中, c i c_i ci表示余数为 i i i时的前序和的个数。

但是这里会有重复的情况,因此,我们需要去除掉这里多算的所有重复情况的个数。由于题目中已知数组是非递减的,因此,如果满足有两个子数组 ( n i ⋯ n j ) (n_i \cdots n_j) (ni⋯nj)与 ( n l ⋯ n r ) (n_l \cdots n_r) (nl⋯nr)完全相同,那么必有这些数的元素必然完全相同。

因此,我们只需要找出所有连续的相同元素的子串,考虑其中会产生多少个重复计算的数组个数即可。而要使得若干个相同元素的和被 k k k整除,那么其连续的个数必然为 k k k与 k k k和该元素的最大公约数的除数的倍数。而其被多记的次数就是该数组的长度减去对应的倍数的个数。

2. 代码实现

我们将其翻译为python代码语言就是:

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 = 0
        while idx < n:
            rb = bisect.bisect_right(nums, nums[idx])
            m = rb - idx
            if k == 1:
                ans -= m * (m+1) // 2 - m
            else:
                l = k // gcd(k, nums[idx])
                for i in range(l, m, l):
                    ans -= m-i
            idx = rb
        return ans

提交代码评测得到:耗时311ms,占用内存41.28MB。

相关推荐
Miraitowa_cheems1 小时前
LeetCode算法日记 - Day 106: 两个字符串的最小ASCII删除和
java·数据结构·算法·leetcode·深度优先
小白程序员成长日记1 小时前
2025.11.12 力扣每日一题
算法·leetcode·职场和发展
未若君雅裁2 小时前
LeetCode 51 - N皇后问题 详解笔记
java·数据结构·笔记·算法·leetcode·剪枝
Kuo-Teng3 小时前
LeetCode 198: House Robber
java·算法·leetcode·职场和发展·动态规划
橘颂TA3 小时前
【剑斩OFFER】算法的暴力美学——除自身以外数组的乘积
算法·leetcode·职场和发展·结构与算法
Espresso Macchiato5 小时前
Leetcode 3748. Count Stable Subarrays
算法·leetcode·职场和发展·leetcode hard·leetcode 3748·leetcode周赛476·区间求和
天选之女wow9 小时前
【Hard——Day4】25.K 个一组翻转链表
数据结构·算法·leetcode·链表
Dream it possible!14 小时前
LeetCode 面试经典 150_二叉树_二叉树中的最大路径和(77_124_C++_困难)(DFS)
c++·leetcode·面试·二叉树
做怪小疯子19 小时前
LeetCode 热题 100——子串——和为 K 的子数组
算法·leetcode·职场和发展