What Is the Modulo Operation? Every Coding Interview Pattern That Uses It

June 18, 20269 min read
dsaalgorithmsinterview-prepleetcode
What Is the Modulo Operation? Every Coding Interview Pattern That Uses It
TL;DR
  • The modulo operation (a % b) returns the remainder after dividing a by b, always in the range [0, b-1] for positive b
  • Python returns non-negative modulo results; Java, C++, and JS return results with the sign of the dividend — a silent bug for circular indexing
  • Circular array indexing requires ((i - 1) % n + n) % n in Java/C++ to guard against negative indices
  • Large-number DP must apply % (10^9 + 7) after every addition and multiplication, not just at the return statement
  • Digit extraction peels the last digit with n % 10 and removes it with n // 10, generalizing to any base
  • Division does not distribute over modulo; use the modular inverse (pow(b, m-2, m) in Python) when you need to divide under modulo

Division answers one question: how many times does b fit into a? The modulo operation answers the other one: what's left over?

7 % 3 = 1. Three goes into seven twice. Two times three is six. The leftover is one.

That leftover shows up everywhere in coding interviews. Circular arrays, hash buckets, large-number DP, digit extraction, divisibility checks. Once you see it, you can't un-see it. You'll start spotting % n in your dreams.

The Modulo Operation: A Division You Already Know

Modulo gives you the remainder of integer division. When you write a % b, you're asking: after dividing a by b as many full times as possible, what's left?

10 % 3 # 1 (3 goes into 10 three times = 9, leftover = 1) 15 % 5 # 0 (5 goes into 15 exactly, no leftover) 7 % 10 # 7 (10 doesn't fit into 7 even once, so 7 is the leftover) 2 % 2 # 0 (divides evenly)

The formal relation is a = b * q + r, where q is the quotient and r is the remainder. You rarely need to write it that way, but it explains the formal name: the modulo operation finds r.

The result of a % b is always in the range [0, b-1] for positive b. That fixed bound is the whole point. No matter how large a gets, modulo maps it into a predictable range. Giant number in, small tidy number out. Magic.

O(1). No Exceptions Worth Worrying About

Both time and space are O(1). Modulo is a single arithmetic instruction on fixed-size integers. Nothing loops. Nothing allocates. Your interviewer will not be impressed, but they also won't be unimpressed, which is exactly where you want to be on complexity questions for primitive ops.

The only footnote: Python's int can hold arbitrarily large numbers, and modulo on a k-digit number takes O(k). In practice, every interview problem works within 64-bit bounds, so O(1) is what you say.

The Language Trap Nobody Mentions

Most languages use % for modulo. The syntax is universal. The behavior with negative numbers is not. This is where people get ambushed.

# Python print(10 % 3) # 1 print(-7 % 3) # 2 (Python: result always matches sign of divisor) print(-7 % -3) # -1
// Java System.out.println(10 % 3); // 1 System.out.println(-7 % 3); // -1 (Java: result matches sign of dividend)
// TypeScript / JavaScript console.log(10 % 3); // 1 console.log(-7 % 3); // -1 (same as Java)
// C++ cout << 10 % 3; // 1 cout << -7 % 3; // -1 (same as Java)

Python is the outlier. In Python, modulo always returns a non-negative result when the divisor is positive. Every other mainstream interview language returns a result with the same sign as the dividend. Python went its own way here, and honestly? Python is right. But "right" doesn't matter if you switch languages mid-prep and forget.

Two-panel meme showing "what is modulo?" with a confused and then enlightened face Yes, it IS just the leftover from division. And no, it does not behave the same in Java.

This bites you the moment you use modulo to wrap a circular index and the index goes negative. In Python, (-1) % n gives n - 1, exactly what you want for circular wrap-around. In Java or C++, it gives -1, which crashes your array access. Silently. Beautifully. Right when the interviewer is watching.

The defensive fix works in any language:

int safeModulo(int a, int b) { return ((a % b) + b) % b; }

Adding b before the second modulo ensures the result is non-negative. If a % b was already non-negative, adding b and taking modulo again brings it back to the right value. Memorize this. Tattoo it somewhere.

Five Interview Patterns That Use Modulo

Circular Array Indexing

You have an array of size n and you need to wrap around: index 0 comes after index n-1. Modulo handles this in one line.

next_position = (current + 1) % n prev_position = (current - 1 + n) % n # +n guards against negative

LeetCode 622 (Design Circular Queue), 918 (Maximum Sum Circular Subarray), and 189 (Rotate Array) all follow this exact pattern. Any problem with "circular," "ring," or "rotate" in the title is probably using it. You should feel the % n loading in your fingers before you finish reading the problem statement.

Divisibility and Even/Odd

The simplest form. n % 2 == 0 means even. More generally, n % k == 0 means k divides n exactly. Simple, but don't underestimate how many problems hide behind it.

def is_prime(n: int) -> bool: if n < 2: return False for i in range(2, int(n**0.5) + 1): if n % i == 0: return False return True

The prime sieve (LeetCode 204), fizzbuzz variants, and any problem that partitions numbers by remainder class rely on this. When a problem asks you to group numbers by some property tied to division, think modulo first.

Digit Extraction

To peel digits off a number from right to left, use % 10 to grab the last digit and floor division by 10 to remove it.

def digit_sum(n: int) -> int: total = 0 while n > 0: total += n % 10 n //= 10 return total

This loop appears in LeetCode 7 (Reverse Integer), 9 (Palindrome Number), 258 (Add Digits), and 263 (Ugly Number). The pattern generalizes to any base: % k gives the last digit in base k. It's like unzipping a number one digit at a time.

Hash Bucket Computation

Every hash table maps a key to a bucket using modulo:

bucket_index = hash(key) % table_size

You won't implement this from scratch in most interviews, but knowing it explains why collision probability rises as the table fills, and why hash table sizes are often primes. Primes distribute remainders more evenly, reducing clustering. Your hash table has opinions about number theory.

Large-Number DP (The mod 10^9+7 Pattern)

Counting problems often ask for the answer modulo 10^9+7 because the true answer can have millions of digits. You maintain the result modulo a prime throughout the computation.

MOD = 10**9 + 7 def count_ways(n: int) -> int: dp = [0] * (n + 1) dp[0], dp[1] = 1, 1 for i in range(2, n + 1): dp[i] = (dp[i-1] + dp[i-2]) % MOD return dp[n]

This works because modular arithmetic distributes over addition and multiplication: (a + b) % m == ((a % m) + (b % m)) % m. So applying modulo at each step produces the same final result as applying it at the very end, without intermediate overflow.

Apply % MOD after every addition and multiplication, not just at the return statement. In Python, skipping this means multiplying astronomical numbers and grinding the runtime to a crawl. In Java or C++, integers silently overflow to negative values and you spend the next ten minutes convinced you have a logic bug.

The value 10^9+7 is not arbitrary. It's the largest prime that fits in a 32-bit integer, and its square fits in a 64-bit integer. Multiplying two values below 10^9+7 and then taking modulo never overflows a 64-bit integer. For the full math, the modular arithmetic guide covers congruences and why this works.

Three Bugs That Show Up in Interviews

Bug 1: Circular index with negative step. Using (i - 1) % n in Java or C++ when i might be 0. Result is -1, which crashes. Fix: ((i - 1) % n + n) % n.

Bug 2: Forgetting modulo in a loop. In Java and C++, integers overflow silently and wrap to negative values. If your DP answers suddenly come out negative, missing % MOD is almost always why.

Reaction meme showing someone realizing they accidentally caused a program crash Discovering your DP returns -748293744 because you forgot % MOD at step 3 of 47.

See integer overflow in coding interviews for a full breakdown.

Bug 3: Dividing inside a modular context. (a / b) % m is not (a % m) / (b % m). Division does not distribute over modulo the way addition and multiplication do. If you need to divide under modulo, you need the modular inverse: a number b_inv such that (b * b_inv) % m == 1. For prime m, Python's three-argument pow(b, m-2, m) computes this in O(log m). A rarer topic, but it shows up in combinatorics problems and will absolutely derail your interview if you assume division works like addition.

How to Not Lose Points on a Pattern You Already Know

When a problem uses modulo, interviewers watch for two things. First, do you recognize when it applies? Cyclic access, "find the remainder," large outputs, digit extraction are all signals you should name out loud. Second, do you handle negative inputs correctly for the language you're using?

A candidate who writes ((i - 1) % n + n) % n and explains why is demonstrating real language-level precision. A candidate who writes (i - 1) % n and doesn't consider the negative case leaves the interviewer wondering whether they've thought it through, or whether they just copied a solution they half-remember.

You don't need to memorize this as a rule. Just ask yourself: can the left side of my modulo ever be negative? If yes, add the guard.

If you want to practice spotting these patterns in real time, SpaceComplexity runs voice-based DSA mock interviews where you explain your reasoning out loud and get rubric-based feedback, including on whether you caught edge cases like this one.

Further Reading