📌  相关文章
📜  Array 中乘积可被 K 整除的对数(1)

📅  最后修改于: 2023-12-03 15:13:29.467000             🧑  作者: Mango

Array 中乘积可被 K 整除的对数

问题描述:

给定一个整数数组 nums 和一个整数 k ,你需要返回 nums 中乘积为 k 的倍数的不同组合的个数。

示例:

输入: nums = [1,2,3,4,5], k = 10

输出: 3

解释: 有三个子数组满足乘积等于10: [2,5], [4,5], [1,2,5]

解题思路:

我们可以在 $O(n^2)$ 的时间复杂度内使用两个指针的方法枚举所有子数组,然后计算乘积是否满足条件。但是,这样的复杂度对于一般的数据范围可能会超时。因此,我们需要寻找更高效的方法。

根据乘法原理,我们可以将问题转化为计算每个数字对 k 取模的余数,然后计算每个余数能够生成多少个乘积为 k 的倍数的组合。如果余数为 0,则其自身可以构成一组组合,因为它本身就是 k 的一个倍数。如果余数不为 0,我们需要寻找另一个余数与它相乘能够得到 k 的倍数。由于我们只需要计算组合数,因此我们不需要考虑具体的数字是什么,只需要考虑余数的个数即可。

由于乘积可以分解成多个因子的积,我们可以使用哈希表记录每个余数出现的次数,然后计算与其对应余数相乘可以构成的乘积个数。具体地,我们如果当前枚举到 nums[i],则我们需要寻找一个与其对应的余数 nums[i] % k 的取值,使得两个余数的乘积是 k 的倍数。如果 nums[i] % k == 0,则只需要找另一个余数也是 0 的情况,因为 0 乘以任何数都得 0;否则,我们需要找到另一个余数 numj,使得 nums[i] * numj % k == 0。

时间复杂度:

本算法的时间复杂度为 O(n),其中 n 是数组 nums 的长度。具体地,我们只需要枚举数组 nums 一次,对于每个数,我们计算对 k 取模的余数,并将余数的个数存入哈希表中。在计算组合数的时候,我们需要取出每个余数对应的个数进行计算。

空间复杂度:

本算法的空间复杂度为 O(k),其中 k 是给定的参数。由于余数的范围在 0 ~ k-1 之间,因此我们需要使用一个哈希表来存储每个余数出现的个数。

代码实现:

class Solution:
    def subarraysDivByK(self, nums: List[int], k: int) -> int:
        num_dict = {0:1}
        count = 0
        remainder = 0
        for num in nums:
            remainder = (remainder + num) % k
            if remainder in num_dict:
                count += num_dict[remainder]
            num_dict[remainder] = num_dict.get(remainder, 0) + 1
        return count

参考链接:

LeetCode 题解