【力扣】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 <= A.length <= 30000
-10000 <= A[i] <= 10000
2 <= K <= 10000

这是昨天的【每日一题】,当时没想出来,允悲,明明是一道很简单的题,但是窗户纸没捅破就死活想不出来。

算法思路

本来这种题是可以用暴力方法破解的,但是在力扣里大部分的暴力破解都会被检测例子制裁。

class Solution:
    def subarraysDivByK(self, A, K: int) -> int:
        n=0
        res=0
        ls=[0]
        for i in A:
            n+=i
            ls.append(n)
        for i in range(1,len(ls)):
            for j in range(i):
                if (ls[i]-ls[j])%K==0:res+=1
        return res

以上是最暴力最无脑的方法,检查所有的子数组可能性,要说有什么可取之处,就是使用ls保存了所有从0-i的数组和,然后通过减法得到i-j的子数组和。

class Solution:
    def subarraysDivByK(self, A, K: int) -> int:
        n=0
        res=0
        ls={0:1}
        for i in A:
            n+=i
            for j in ls.keys():
                if (n-j)%K==0:
                    res+=ls[j]
            ls[n]=ls.get(n,0)+1
        return res

以上依然是暴力循环,但是又做了一点小优化,虽然没啥用就是了。

PERFECT

但其实这道题的技巧在于!!!(n-j)%K==0实际上等价于n%K==j%K,所以所有的数组和都可以化归到K以内的值,然后保存出现的频率即可。

class Solution:
    def subarraysDivByK(self, A, K: int) -> int:
        n=0
        res=0
        ls={0:1}
        for i in A:
            n+=i
            tp=n%K
            if tp in ls:
                res+=ls[tp]
            ls[tp] = ls.get(tp, 0) + 1
        return res

执行用时 :392 ms, 在所有 Python3 提交中击败了50.00%的用户
内存消耗 :17.7 MB, 在所有 Python3 提交中击败了100.00%的用户

语言表述不透彻,但是有认真思考过的人应该可以看懂算法。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章