LeetCode:974. Subarray Sums Divisible by K - Python

974. 和可被 K 整除的子数组

问题描述:

给定一个整数数组 A,返回其中元素之和可被K整除的(连续非空)子数组的数目

示例:

输入:A = [4,5,0,-2,-3,1], K = 5
输出:7
解释:
有 7 个子数组满足其元素之和可被 K = 5 整除:
[4, 5, 0, -2, -3, 1], [5], [5, 0], [5, 0, -2, -3], [0], [0, -2, -3], [-2, -3]

提示:

  1. 1 <= A.length <= 30000
  2. -10000 <= A[i] <= 10000
  3. 2 <= K <= 10000

问题分析:

这个题目应该也是18年一个公司的秋招题目,特别的巧妙的方法自己也没有想到。都笨方法,看了官方的解答,才恍然大悟,感觉更像是一个数学题目。现在总结一下:

(1)可以设 P[i] = (A[0] + A[1] + ... + A[i])%K,现在仔细想一下,如果P[i] = P[j],且j>i。是不是可以得出来子序列A[i, j] 是可以被K整除的。想想为什么?因为这两个子序列余数相同,很显然(A[0] + A[1] + ... + A[i]+... + A[j]) - (A[0] + A[1] + ... + A[i]) = A[i, j] 的差的余数一定为0,也就是整除了。

(2)现在问题就简化了很多:

  1. 首先,要求出这些余数来,也就是P[i]
  2. 然后把相同的余数,它们的个数统计出来。
  3. 例如,某一个余数的个数为5,是不是可以的出来,5 *(5-1)//2 = 10(任意两两配对)。
  4. 依次类推,把所有的结果求出,然后求和即可。

Python3实现:

方法一(官方版):

import collections


class Solution():
    def subarraysDivByK(self, A, K):
        P = [0]
        for x in A:
            P.append((P[-1] + x) % K)

        count = collections.Counter(P)
        return sum(v*(v-1)/2 for v in count.values())

方法二:

# @Time   :2018/06/17
# @Author :LiuYinxing
# 数学


from collections import defaultdict


class Solution:
    def subarraysDivByK(self, a, k):
        counts = defaultdict(int)  # 用于对各个余数进行计数
        counts[0] = 1  # 因为 0 本身就是一个,所以要先初始化
        cur_sum = 0  # 记录当前列表的和
        ans = 0  # 记录可被整数的子序列数
        for num in a:
            cur_sum += num
            mod = cur_sum % k  # 取余
            ans += counts[mod]  # 累计
            counts[mod] += 1  # 计数
        return ans


if __name__ == '__main__':
    solu = Solution()
    A, K = [4, 5, 0, -2, -3, 1], 5
    print(solu.subarraysDivByK(A, K))

更喜欢第二种方法

声明: 总结学习,有问题或不当之处,可以批评指正哦,谢谢。

题目链接参考链接

猜你喜欢

转载自blog.csdn.net/XX_123_1_RJ/article/details/86549560
今日推荐