523. Continuous Subarray Sum - Explanation

Problem Link

Description

You are given an integer array nums and an integer k, return true if nums has a good subarray or false otherwise.

A good subarray is a subarray where:

  • its length is at least two, and
  • the sum of the elements of the subarray is a multiple of k.

Note:

  • A subarray is a contiguous part of the array.
  • An integer x is a multiple of k if there exists an integer n such that x = n * k. 0 is always a multiple of k.

Example 1:

Input: nums = [23,2,4,6,7], k = 6

Output: true

Explanation: [2,4] is a continuous subarray of size 2 whose sum is 6.

Example 2:

Input: nums = [23,2,6,4,7], k = 6

Output: true

Explanation: [23,2,6,4,7] is an continuous subarray of size 5 whose sum is 42, which is a multiple of 6..

Example 3:

Input: nums = [23,2,6,4,7], k = 13

Output: false

Constraints:

  • 1 <= nums.length <= 1,00,000
  • 0 <= nums[i] <= 1,000,000,000
  • 0 <= sum(nums) <= ((2^31)-1)
  • 1 <= k <= ((2^31)-1)


Topics

Company Tags

Please upgrade to NeetCode Pro to view company tags.



Prerequisites

Before attempting this problem, you should be comfortable with:

  • Hash Map - Used for O(1) lookups to store and retrieve the first occurrence of each remainder value
  • Prefix Sum - Computing cumulative sums to efficiently determine subarray sums
  • Modular Arithmetic - Understanding how remainders work and that equal remainders at two indices indicate a sum divisible by k

1. Brute Force

Intuition

The straightforward approach is to check every possible subarray of size at least 2 and see if its sum is a multiple of k. A number is a multiple of k if dividing it by k leaves no remainder. We iterate through all starting and ending positions to examine every valid subarray.

Algorithm

  1. Iterate through all possible starting indices i from 0 to n-2 (we need at least 2 elements).
  2. For each starting index, maintain a running sum starting with nums[i].
  3. Extend the subarray by iterating through ending indices j from i+1 to n-1, adding each element to the running sum.
  4. After adding each element, check if the sum is divisible by k (sum % k == 0).
  5. If we find such a subarray, return true immediately.
  6. If no valid subarray is found after checking all possibilities, return false.
class Solution:
    def checkSubarraySum(self, nums: List[int], k: int) -> bool:
        for i in range(len(nums) - 1):
            sum = nums[i]
            for j in range(i + 1, len(nums)):
                sum += nums[j]
                if sum % k == 0:
                    return True
        return False

Time & Space Complexity

  • Time complexity: O(n2)O(n ^ 2)
  • Space complexity: O(1)O(1)

2. Prefix Sum + Hash Map

Intuition

The key insight is based on modular arithmetic. If the prefix sum up to index i has remainder r when divided by k, and the prefix sum up to index j also has remainder r, then the subarray from i+1 to j has a sum that is a multiple of k. This is because (prefixSum[j] - prefixSum[i]) % k = 0 when both have the same remainder. We use a hash map to store the first index where each remainder was seen.

Algorithm

  1. Create a hash map to store remainder values and their first occurrence index. Initialize it with {0: -1} to handle cases where the prefix sum itself is divisible by k.
  2. Maintain a running total as we iterate through the array.
  3. For each element, add it to the total and compute the remainder (total % k).
  4. If this remainder exists in the map and the subarray length is at least 2 (current index minus stored index > 1), return true.
  5. If the remainder is not in the map, store it with the current index.
  6. Return false if no valid subarray is found.
class Solution:
    def checkSubarraySum(self, nums: List[int], k: int) -> bool:
        remainder = {0: -1}  # remainder -> end index
        total = 0

        for i, num in enumerate(nums):
            total += num
            r = total % k
            if r not in remainder:
                remainder[r] = i
            elif i - remainder[r] > 1:
                return True

        return False

Time & Space Complexity

  • Time complexity: O(n)O(n)
  • Space complexity: O(k)O(k)

Where nn is the size of the array numsnums and kk is the number that a subarray sum needs to be multiple of.


Common Pitfalls

Forgetting to Initialize Hash Map with {0: -1}

The hash map must be initialized with remainder 0 at index -1 to handle cases where the prefix sum itself (from index 0 to current) is divisible by k. Without this, you miss valid subarrays that start from index 0.

# Wrong - misses subarrays starting at index 0
remainder = {}

# Correct
remainder = {0: -1}

Not Enforcing Minimum Subarray Length of 2

The problem requires the subarray to have at least 2 elements. A common mistake is checking i - remainder[r] >= 1 instead of > 1, which would accept single-element subarrays.

# Wrong - accepts single-element subarrays
elif i - remainder[r] >= 1:

# Correct - ensures at least 2 elements
elif i - remainder[r] > 1:

Updating the Hash Map When Remainder Already Exists

When the same remainder is seen again, you should NOT update its index. We need the earliest index for each remainder to maximize the subarray length and correctly detect valid subarrays. Updating would shrink the window and potentially miss valid answers.