UMPIRE
- [U]nderstand the problem, ask questions and come up with corner test cases.
- [M]atch the leetcode pattern
- [P]lan to using pattern template and data structures
- [I]mplement the code
- [R]eview by running the example and corner test cases
- [E]valuate time and space complexity

Understand

  • Need to count subarrays where cnt is number of element such that nums[i] % modulo == k and cnt % modulo == k

Brute force

  • Generate all sub arrays, calculate cnt and verify cnt % modulo == k.
  • Time complexity O(n^2) fails for constraint n = 10^5

Match

Sliding window

  • I thought we can break it smaller problem count subarrays whose cnt = x and apply sliding window for each x value. where x is i * modulo + k for i in 0, 1, 2, .. and x < len(nums)
  • Sliding window will not work as there is no clear condition when to shrink the window.

Subarray ending at index i trick

Prefix sum

  • We can use prefix sum
  • This is similar to Subarray sum equals k with modulo twist.

Plan

  • In subarray sum equals k, prefix[r] - prefix[left] = k which translates to prefix[r] - k = prefix[left]
res = 0
prefix = defaultdict(int)
prefix[0] = 1
s = 0
for n in nums:
    s += n
    res += prefix[s - k]
    prefix[s] += 1
return res
  • Similarly, (prefix[right] - prefix[left]) % modulo = k translated to (prefix[right] - k + modulo) mod modulo = prefix[left] mod modulo
(prefix[right] - prefix[left]) mod modulo = k
=> prefix[right] - prefix[left] = k + c * modulo
=> prefix[right] - k = prefix[left] + c * modulo 
=> (prefix[right] - k) mod modulo = (prefix[left] + c * modulo) mod modulo  -- using modulo both side
=> (prefix[right] - k) mod modulo =  prefix[left] mod modulo  -- using (a + c.m) mod m = a mod m
=> (prefix[right] - k + modulo) mod modulo =  prefix[left] mod modulo -- using  a mod m = (a + c.m) mod m
res = 0
prefix = defaultdict(int)
prefix[0] = 1
c = 0
for n in nums:
    c += ((n % modulo = k) if 1 else 0)
    res += prefix[c - k + modulo]
    prefix[c % modulo] += 1
return res

Implement

res = 0
prefix = defaultdict(int)
prefix[0] = 1
c = 0
for n in nums:
    c += ((n % modulo = k) if 1 else 0)
    res += prefix[c - k + modulo]
    prefix[c % modulo] += 1
return res

Review

Evaluate

  • Time complexity: O(n)