題目描述
給定一個整數數組 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%的用戶
語言表述不透徹,但是有認真思考過的人應該可以看懂算法。