class Solution:
def minSubarray(self, A: List[int], p: int) -> int:
""" tc O(N) sc O(N)
case1 no need to remove sum(A) % p == 0
case2 there is a min length subarray A[i:j], => [total - sum(A[i:j])] % p == 0 ==> total%p == sum(A[i:j])%p = rem
==> 1. caculate running sum `rsum`, store `rsum%p` 2. find prev A[:i]'s rmod s.t. {psum(A[:j]) - psum(A[:i])}%p == rem ==> (psum(A[:j])- rem)%p = psum(A[:i]) , so we need just to record psum(A[:k]) and look up if previous there is psum(A[:pre]) exit
case3: impossible to remove sum(A) < p
`rsum`: current prefix remainder;
`total`
hmap track 1.running sum modulo 2. most recent position for that modulo
as loop array, look up a `comp` modulo in hmap and track min size
"""
rem = sum(A)%p
if rem == 0:
return 0
last,n = {0:-1},len(A)# 0:-1 when A[0] == remainder: we get min window size = 1
rmod,min_w = 0,n
for i,a in enumerate(A):
rmod = (rmod + a)%p
if (rmod - rem)%p in last: # (r_mod - mod + p)%p # here + p to make % non-negtive
min_w = min(min_w,i-last[(rmod - rem)%p]) # if compliment is recorded,try to update min (j,i]
last[rmod] = i
return min_w if min_w < n else -1