Your country

Tools that support it use your country for local currency, number formats, units and paper size. Your choice is saved only in this browser.

Type a name or a two-letter code. Use the up and down arrow keys to move through the countries, Enter to choose one and Escape to close.

Coding Interview Patterns  Module 6 – Prefix sums and difference arrays

Divisibility with prefix remainders

Count the stretches of an array whose total is a multiple of k by grouping running totals by remainder, with negative remainders fixed in every language.

  • Intermediate
  • 20 minutes
  • Examples run with Python 3.14.8, Pyodide 314.0.7, Node.js 24.21.0, quickjs 0.32.0 and Java temurin-25.0.4+101.0.LTS
  • By MySmartCoPilot
Free intro, Pro: 5 of 20 minutes free
Free: The problem: stretches that fill whole crates. With a pass: the other 9 sections and 3 interview answers, about 15 minutes.

What you will learn

  • Count subarrays whose sum is divisible by k from the remainders of running totals
  • Normalise negative remainders in Java, C++, Go and JavaScript
  • Detect a divisible subarray of at least two elements
  • Choose between a list of k counters and a hash map from the limits on k

Before you start

What you’ll learn · Before you start

What you will learn

  • Count subarrays whose sum is divisible by k from the remainders of running totals
  • Normalise negative remainders in Java, C++, Go and JavaScript
  • Detect a divisible subarray of at least two elements
  • Choose between a list of k counters and a hash map from the limits on k

Before you start

On this page

Testing every stretch of a 200,000-entry order log for a total that is a multiple of k takes about 2 × 10¹⁰ tests. A stretch’s total is divisible by k when it leaves no remainder, so the question is about remainders, not about the totals themselves. Counting such stretches is a close relative of counting stretches with a fixed total: running total: The sum of the items seen so far, updated with one addition per item, so the totals of every prefix of a list cost one pass instead of a new sum each. More in “Getting unstuck: heuristics and using hints” turn each stretch into a difference of two numbers, and divisibility only cares about what those numbers leave over after division by k. Counting those remainders takes a list of k counters when k is small, or a hash map when it is large.

Below are an original problem about crates and cancelled orders, the cost of trying every stretch at its limits, and the signal that turns it into a single pass.

The problem: stretches that fill whole crates

The problem

A wholesaler ships units in crates of k. Its order log lists, in order, how many units each entry adds to the shipment: an order is positive, a cancellation that takes units back is negative. A stretch of consecutive entries can be packed or unpacked in whole crates exactly when its net total is a multiple of k: 0, k, −k, 2k and so on. Count those stretches. Limits: 1 ≤ n ≤ 2 × 10⁵, −10⁵ ≤ units[i] ≤ 10⁵ and 1 ≤ k ≤ 10⁵.

  1. units = [3, -8, 3, 5, 8, -9] and k = 5 give 4: entries 0 to 1 and entries 1 to 2 both net −5, one crate taken back; entries 1 to 3 net 0; entry 3 alone is 5.
  2. [4, 2, 6] and k = 3 give 3: [4, 2], [6] and the whole log.
  3. [1, 2, 4] and k = 7 give 1: only the whole log, which nets 7.

The brute force: every stretch, tested

For each first entry, extend the stretch one entry at a time, keep its net total, and test whether k divides it. The test is O(1), but there are n(n + 1)/2 stretches. Step through the 21 tests of the first example:

Interactive · step by step Every stretch of the first log, tested Step through the first entries. Each step extends the stretch to the end of the log and tests every net total it passes.
Every stretch of the first log, tested, step 8 of 8. Showing First entry (entry 5), Net totals of this row (−9), Totals tested (21), Multiples of 5 (4: entry 3 alone). In focus: Totals tested, Multiples of 5.First entryentry 5Net totals of this row−9Totals tested21Multiples of 54: entry 3 alone

The drawing shows the whole scene; its 8 steps are listed below.

Every step as text
  1. The log. The log is [3, −8, 3, 5, 8, −9] and a crate holds 5 units. For each first entry, the brute force extends the stretch one entry at a time and tests whether 5 divides its net total.
  2. First entry 0. From entry 0 the net totals are 3, −5, −2, 3, 11 and 2. Only −5 is a multiple of 5: entries 0 to 1 take one crate back.
  3. First entry 1. From entry 1 the totals are −8, −5, 0, 8 and −1. Two are multiples of 5: entries 1 to 2 net −5, and entries 1 to 3 net 0.
  4. First entry 2. From entry 2 the totals are 3, 8, 16 and 7. None of them is a multiple of 5.
  5. First entry 3. From entry 3 the totals are 5, 13 and 4. Entry 3 alone fills one crate.
  6. First entry 4. From entry 4 the totals are 8 and −1, and neither is a multiple of 5.
  7. First entry 5. The last row has one stretch, entry 5 alone, with a net total of −9.
  8. 21 tests for 4 stretches. 6 entries made 6 + 5 + 4 + 3 + 2 + 1 = 21 tests, n(n + 1)/2, to find 4 stretches. At 200,000 entries the same loops make 20,000,100,000 tests.

The same loops on longer logs, with the time they take:

Every stretch tested, and the time it would take at the limit Python · brute/crates_brute.py
"""Counts the stretches of an order log whose net units fill whole crates, by checking every stretch, and times it."""
import random
import time


def full_crate_stretches_brute(units, k):
    """For each first entry, extend the stretch one entry at a time and test its total."""
    count = 0
    for first in range(len(units)):
        net = 0
        for last in range(first, len(units)):
            net += units[last]
            count += net % k == 0
    return count


print(full_crate_stretches_brute([3, -8, 3, 5, 8, -9], 5))
print(full_crate_stretches_brute([4, 2, 6], 3))
print(full_crate_stretches_brute([1, 2, 4], 7))

rng = random.Random(3)
timings = []
for n in (1_000, 2_000):
    units = [rng.randint(-100_000, 100_000) for _ in range(n)]
    started = time.perf_counter()
    full_crate_stretches_brute(units, 12)
    timings.append((time.perf_counter() - started) / (n * (n + 1) // 2))
    print(f"{n:,} entries: {n * (n + 1) // 2:,} totals tested")

n = 200_000
minutes = timings[-1] * n * (n + 1) / 2 / 60
print(f"{n:,} entries: {n * (n + 1) // 2:,} totals, roughly {minutes:,.0f} minutes at the speed of the last run")

Output

4
3
1
1,000 entries: 500,500 totals tested
2,000 entries: 2,001,000 totals tested
200,000 entries: 20,000,100,000 totals, roughly 53 minutes at the speed of the last run

This output changes from run to run: the time depends on the computer and on what else it is doing

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 crates_brute.py

At 2 × 10⁵ entries that is 2 × 10¹⁰ tests. The last line turns the measured speed into the time for the full log, far beyond any time limit, and compiled code at a rough 10⁸ simple steps a second would still need more than three minutes.

Checkpoint

Check: Which stretches fill whole crates · The brute force and its cost

  1. Question 1 of 2 Crates hold 5 units. Which net totals of a stretch can be packed or unpacked in whole crates?

    Choose every answer that is right.

    Show the answer: Question 1 of 2

    Answer:

    • −5
    • 0
    • 10

    A stretch counts exactly when its net total is a multiple of k: 0, k, −k, 2k and so on, negative totals included.

  2. Question 2 of 2 How many totals does the brute force test on a log of 1,000 entries?

    Type a number.

    Show the answer: Question 2 of 2

    Answer: 500500 totals

    One test per stretch: n(n + 1)/2 = 1,000 × 1,001 / 2 = 500,500, the number the program printed.

What to notice

Whether a number is a multiple of k depends only on its remainder after division by k, and every stretch total is the difference of two running totals. Together, those two facts turn a question about all n(n + 1)/2 stretches into a question about the n + 1 running totals and their remainders. Watch the negative entries: a running total can drop below zero, and not every language agrees on the remainder of a negative number.

Checkpoint

Check: What points to remainders

  1. One question Whether the net total of a stretch is a multiple of k depends on what?

    Choose one answer.

    Show the answer: One question

    Answer: Only on the remainder that total leaves after division by k

    That fact, and that every stretch total is the difference of two running totals, turn the question into one about the n + 1 running totals and their remainders.

The questions below cover the problem, its brute force and the signal; a wrong answer brings an easier one on the same idea, a right one a harder one.

Practice that adapts to you

Practise this lesson

7 questions about 9 ideas of this lesson. Each answer is explained at once, and what you get right is kept in this browser.

  1. Question 1 of 7 A stretch has a net total of 0: its orders and cancellations cancel out. Does it count?

    Choose one answer.

    Show the answer: Question 1 of 7

    Answer: Yes: 0 is a multiple of k, zero crates

    The multiples of k are 0, k, −k, 2k and so on, so a stretch that nets 0, such as entries 1 to 3 of the first example, counts.

  2. Question 2 of 7 units = [5, -5, 5] and k = 5. How many stretches of one or more consecutive entries have a net total that is a multiple of 5?

    Type a number.

    A hint

    List the six stretches and their nets.

    Show the answer: Question 2 of 7

    Answer: 6 stretches

    The six stretches net 5, 0, 5, −5, 0 and 5, and every one of them is a multiple of 5, negatives and zeros included.

  3. Question 3 of 7 With k = 5, a stretch of cancellations takes 10 units back, a net total of −10. Does it count?

    Choose one answer.

    Show the answer: Question 3 of 7

    Answer: Yes: −10 is −2 × 5, two crates unpacked

    A stretch can be packed or unpacked in whole crates exactly when its net total is a multiple of k, whatever its sign.

  4. Question 4 of 7 How many totals does the brute force test on a log of 6 entries?

    Type a number.

    Show the answer: Question 4 of 7

    Answer: 21 totals

    6 + 5 + 4 + 3 + 2 + 1 = 21, n(n + 1)/2, as the step-through of the first log shows.

  5. Question 5 of 7 At the limit there are about 2 × 10¹⁰ stretches. At a rough 10⁸ simple steps a second, about how many seconds would compiled code need?

    Type a number.

    Show the answer: Question 5 of 7

    Answer: 200 seconds

    2 × 10¹⁰ ÷ 10⁸ = 200 seconds, more than three minutes, and Python is slower still.

  6. Question 6 of 7 The running totals of [3, -8, 3] are 0, 3, −5 and −2, the empty prefix first. Which difference gives the total of entries 1 to 2?

    Choose one answer.

    Show the answer: Question 6 of 7

    Answer: −2 − 3 = −5, the total after 3 entries minus the total after 1

    The stretch of entries i to j has total P(j + 1) − P(i): here P(3) − P(1) = −2 − 3 = −5.

  7. Question 7 of 7 Which two facts turn a question about all n(n + 1)/2 stretches into one about the n + 1 running totals?

    Choose one answer.

    Show the answer: Question 7 of 7

    Answer: Divisibility by k depends only on the remainder, and every stretch total is the difference of two running totals

    This is the signal of the pattern: a condition on stretch totals that depends only on remainders points to running totals grouped by remainder.

Equal remainders, counted in one pass Pro: opens with a Pro, Premium or Ultimate pass

In this part:

  • Why equal remainders mean a multiple of k
  • The sign of a remainder in 14 languages, recorded
  • The count in 14 languages
  • Three slips, caught by a stress test
  • A divisible stretch of at least two entries
  • Four variants, each a small change to the count
  • Practise: stretches that leave r units over
    • Count the stretches that leave r units over
  • Interview questions
    • A JavaScript solution counts the subarrays whose sum is divisible by k by counting equal values of total % k over the running totals. It matches the brute force on every test with non-negative values and fails once negative values appear. Find the bug without running the code, and give a fix that also works in Java, C++ and Go.
    • Your count of subarrays with sums divisible by k keeps an array of k counters, one per remainder. The limits change to k up to 10⁹ with n up to 2 × 10⁵ and values up to 10⁹ in absolute value. What breaks, what do you change, and what does each choice cost in time and memory?
    • Decide whether some run of at least two consecutive values has a sum that is a multiple of k, for up to 10⁵ values. Why is the remainder-counting map not enough as it is, what do you store instead, and why must that map never be overwritten?
  • Key takeaways

2 diagrams · 5 runnable examples (Java, Python) · 1 exercise with sample tests · 3 interview answers · about 38 minutes

Opening this part with your pass…

This part opens with any MySmartCoPilot pass.

  • Pro pass · 1 week₹79$2.99
  • 30 days₹179$5.99
  • 1 year₹1,699$45

One payment; a pass never renews. The price shown is the total you pay: no fees or charges are added at checkout.

It also opens every other in-depth part in Learn and every Pro tool. Sales are final, except where the law gives you a right to withdraw, for example in the EU and the UK (refund policy).

References

Related tools

Report a problem with this lesson

Quick answers and tool search

Type to search tools or to get a quick answer, for example 18% of 2500. Use the up and down arrow keys to move through the results, Enter to choose, and Escape to close.