问题描述
给定一个整数数组 A,返回其中元素之和可被 K 整除的(连续、非空)子数组的数目。
例子
暴力破解1
直接遍历两遍数组O(n2),然后对子数组进行求和O(n),时间复杂度为O(n3)
class Solution:
def subarraysDivByK(self, A: List[int], K: int) -> int:
#暴力破解1
x=0
for i in range(len(A)):
for j in range(i+1,len(A)+1):
if sum(A[i:j])% K==0:#判读是否整除K
#print(A[i:j])
x+=1
return x
暴力破解2
先对数组进行求前缀和,然后再遍历两边数组,这样的时间复杂度为O(n*2)
class Solution:
def subarraysDivByK(self, A: List[int], K: int) -> int:
x=0
B={}
B[0]=0
for i in range(1,len(A)+1):#求前缀和数组,
B[i]=B[i-1]+A[i-1]
for i in range(len(A)):
for j in range(i+1,len(A)+1):
if (B[j]-B[i])%K==0:#直接得到字数组的和
#print("i",i,"j",j)
x+=1
return x
同余解法
思想:两个对K余数相同的位置--->的中间的差值 --->对K的余数必定为 --->0。
首先求每个位置的前缀和,然后求每个位置对K的余数,然后对这些余数进行计数,
然后用排列组合的方式求答案。
简单版本
class Solution:
def subarraysDivByK(self, A: List[int], K: int) -> int:
x=0
C={}#统计数量的字典
B={}#求余后的字典
B[0]=0 #0前面的和的是0
for i in range(1,len(A)+1):
B[i]=(B[i-1]+A[i-1])%K
if B[i] not in C:
C[B[i]]=1
else:
C[B[i]]+=1
for i,j in C.items():#遍历计数字典
if i==0: #如果其余数为0,加上j
x+=j
if j >1: #如果j>1,使用排列组合
x+=(j*(j-1))//2
return x
精简版本
class Solution:
def subarraysDivByK(self, A: List[int], K: int) -> int:
#同余
record = {0: 1}
total, ans = 0, 0
for elem in A:
total += elem
modulus = total % K
same = record.get(modulus, 0)
ans += same
record[modulus] = same + 1
return ans
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/subarray-sums-divisible-by-k/