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 1 – How to approach a coding round

Read constraints to pick the target complexity

Read a coding problem's constraints block in a minute, turn its limits into a target complexity and the patterns that fit it, and check the plan by timing it.

  • Beginner
  • 20 minutes
  • Examples run with Python 3.14.8 and Pyodide 314.0.7
  • By MySmartCoPilot

What you will learn

  • Estimate the operation budget from input limits and the time limit
  • Choose a target complexity class, for example O(n log n) for n up to 2 × 10⁵
  • Measure code instead of trusting folklore numbers

Before you start

On this page

Every online-assessment problem ends with a block of limits, and many people skim past it to start coding. That block is the most direct hint you will get: it tells you how fast the solution must be before you have thought of one. In a live round the limits are often missing, so you ask for them during the clarifying step. This lesson reads limits the way you would under time pressure, maps them to a target complexity and the patterns that usually reach it, and shows how to check a plan by timing it rather than trusting a rule of thumb.

Read the block before the story

Here is an original constraints block of the kind that ends a problem statement:

Constraints

1 ≤ n ≤ 2 × 10⁵. −10⁹ ≤ a[i] ≤ 10⁹. 1 ≤ q ≤ 10⁵ queries. Time limit: 2 seconds per test file. The answer can be large: print it modulo 10⁹ + 7.

Read it in this order, and say the conclusions aloud in a live round:

  1. The largest size. n can be 200,000, so an algorithm that looks at every pair makes about n²/2 = 2 × 10¹⁰ comparisons. That rules out O(n²) before you write anything.
  2. The time limit and your language. Multiply the seconds by the number of simple steps your language does per second. A common planning figure is about 10⁸ a second for compiled code and about 10⁷ for CPython; the DSA track’s lesson on growth rates measures where those figures come from. Two seconds in Python is then a budget of a few times 10⁷ steps.
  3. The other numbers. The values reach 10⁹ in size, q queries come on top of n, and the modulus says the true answer is too big to print. Each of these changes the plan, as the clues below show.

Then compare the step count of each idea with the budget. Here, n log₂ n is about 3.5 million for n = 2 × 10⁵, well inside even the Python budget, so the target is O(n log n) or better, plus a cheap answer to each query.

A target for each size

This list is an estimate, not a law: it assumes a budget of roughly 10⁸ simple steps, about a second of compiled code. Python has about a tenth of that, which moves each boundary down (for O(n²), from about 10,000 to about 3,000).

  • n up to about 10: O(n!) fits, so you can try every order, with backtracking.
  • n up to about 20: O(2ⁿ · n) fits, so you can try every subset, with bitmasks or backtracking.
  • n in the hundreds: O(n³) fits: three nested choices, such as interval dynamic programming.
  • n in the thousands: O(n²) fits: every pair, or a two-dimensional table.
  • n from 10⁵ to 10⁶: aim for O(n log n): sorting, heaps, binary search.
  • n of 10⁷ and more: aim for O(n) or better: one pass, hashing, two pointers, or a formula.

The patterns named here each have a module of their own later in this track. Reading the limits first tells you which modules to think about, and which ones you can rule out without trying them.

Measure instead of trusting rules of thumb

A planning figure is a guess about someone else’s computer. When it matters, measure. Here are the two correct solutions of the step-goal streak from the first lesson of this module, timed on their worst case, a streak that covers every day:

The brute force and the one-pass streak, timed Python · streak_timing.py
# The two correct streak solutions from the first lesson of this module, timed as n grows.
import time


def brute_force(steps, goal):  # start a streak on every day: O(n^2) when the streak is long
    best = 0
    for start in range(len(steps)):
        length = 0
        while start + length < len(steps) and steps[start + length] >= goal:
            length += 1
        best = max(best, length)
    return best


def one_pass(steps, goal):  # O(n)
    best = run = 0
    for count in steps:
        run = run + 1 if count >= goal else 0
        best = max(best, run)
    return best


def best_ms(solution, steps, runs=3):
    """The fastest of a few runs, in milliseconds: slower runs were disturbed by other programs."""
    fastest = float("inf")
    for _ in range(runs):
        start = time.perf_counter()
        solution(steps, 7000)
        fastest = min(fastest, time.perf_counter() - start)
    return fastest * 1000


print("Every day meets the goal, the worst case for the brute force.")
print(f"{'n':>9}  {'brute force':>12}  {'one pass':>10}")
brute_ms = {}
for n in [500, 1_000, 2_000, 100_000]:
    steps = [9000] * n
    if n <= 2_000:  # beyond that the brute force takes too long to wait for
        brute_ms[n] = best_ms(brute_force, steps)
    brute = f"{brute_ms[n]:9.1f} ms" if n in brute_ms else f"{'(skipped)':>12}"
    print(f"{n:>9,}  {brute}  {best_ms(one_pass, steps):7.2f} ms")
estimate = brute_ms[2_000] * (100_000 / 2_000) ** 2 / 1000  # O(n^2): 50 times the n, 2,500 times the time
print(f"Estimated brute force at n = 100,000: about {estimate:,.0f} s, against a 10 s limit for Python.")

Output

Every day meets the goal, the worst case for the brute force.
        n   brute force    one pass
      500        7.5 ms     0.02 ms
    1,000       33.2 ms     0.05 ms
    2,000      146.9 ms     0.10 ms
  100,000     (skipped)     6.28 ms
Estimated brute force at n = 100,000: about 367 s, against a 10 s limit for Python.

This output changes from run to run: the times depend 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 streak_timing.py

Your numbers will differ from the recorded ones, and from run to run, but the shape should be the same. If one row looks out of line, run it again: other programs on the computer disturb short timings.

  • Doubling n roughly quadruples the brute force’s time, because it is O(n²) on this input. The one-pass version roughly doubles, as O(n) should.
  • The estimate for n = 100,000 is minutes, against HackerRank’s 10-second limit for Python. Even a limit ten times as long would not be enough.
  • The one-pass version handles 100,000 days in a few milliseconds in CPython, so in Python the language was never the problem; the algorithm was.

Two habits come from this. First, choose the complexity class before you worry about the language: no time limit makes up for a class that is too slow. Second, before you submit in an online assessment, build the largest input the limits allow (here, 100,000 days that all meet the goal) and time your own solution on it. Sample tests are usually small, so they seldom tell you that a solution is too slow.

The time limit is per language on some platforms. HackerRank’s environment page lists 10 seconds for Python, 4 for Java and Go, and 2 for C and C++. A longer limit does not make an interpreted loop as fast as compiled code, so for loop-heavy plans in Python, budget with the smaller Python figure.

Not affiliated

Based on public information about HackerRank. MySmartCoPilot is not affiliated with HackerRank, and HackerRank’s real time limits may differ from what this lesson describes.

Clues hidden in the limits

Besides the size, other limits point at a technique. None of these is a rule, but each is worth a second look:

The statement says What it often means
Values up to 10⁹ An array with one slot per value is out: sort, or use a hash map
A sum of up to 2 × 10⁵ values of 10⁹ each The total, 2 × 10¹⁴, overflows a 32-bit integer; use 64-bit integers in Java, C++ and Go (Python’s integers have no limit)
q queries on top of n items Scanning for every query costs n × q; prepare once so that each query is O(1) or O(log n)
k ≤ 20 for a small set of choices 2ᵏ subsets is about a million: bitmasks over the k choices
“Print the answer modulo 10⁹ + 7” The answer is a huge count: usually counting with dynamic programming or combinatorics
Up to 10⁴ test cases, with the sum of n at most 2 × 10⁵ The total is bounded, so O(n log n) per test is fine; resetting a big array for every test is not

The overflow line is easy to check: a Java int holds values up to 2,147,483,647, according to the Java Language Specification, far below 2 × 10¹⁴. The last line hides a classic slip. If each of 10⁴ test cases clears an array of 10⁶ counters, the clearing alone costs 10¹⁰ steps, though every test case is small; clear only what the test case used.

In a live round

Say the reading out loud, in one or two sentences: “n is up to two hundred thousand, so comparing every pair is about two times ten to the ten steps. I need O(n log n) or better, so I’m thinking about sorting or a hash map.” It shows the interviewer your plan, and it is the problem-solving signal the rubric in the first lesson looks for.

Scientific Notation Calculator Multiply limits such as 2 × 10⁵ by 2 × 10⁵ and compare the result with your budget. Python Online Compiler Build the largest input the limits allow and time your own solution on it.

Key takeaways

  • Read the constraints block before the story: the largest size, the time limit, then the other numbers.
  • Multiply the time limit by your language’s rate (planning figures: about 10⁸ simple steps a second compiled, 10⁷ in CPython) and compare each idea’s step count with that budget.
  • Sizes map to targets: about 20 means exponential is allowed, a few thousand means O(n²), 10⁵ and up means O(n log n) or better.
  • Limits on values, queries, counts and test cases each hint at a technique, and at a trap.
  • Measure on the largest input the limits allow. The complexity class decides far more than the language does.

Exercise

Exercise · Easy · Python

Find the two readings closest in time

A sensor logs a reading now and then, and the log keeps the time of each reading in seconds. Write closest_gap(times), which returns the smallest number of seconds between any two readings. The times are not in order, and two readings can share a time (the gap is then 0).

The statement comes with this constraints block:

  • 2 <= len(times) <= 200,000
  • 0 <= times[i] <= 10**9
  • Time limit: 2 seconds
closest_gap([40, 7, 25, 31])  # 6: the readings at 25 and 31
closest_gap([5, 90, 5])       # 0: two readings at the same time

Before you write code, read the limits as the lesson does and say which complexity you are aiming for. Comparing every pair passes the short sample tests, but the last test has 20,000 readings and stops a function after 200,000 executed lines, so it fails there, as it would fail the full-size hidden tests of a real assessment.

Starter code · closest.py

def closest_gap(times):
    """The smallest number of seconds between any two of the readings."""
    # Replace this line with your code.
    return 0
The sample tests · test_closest.py
import random
import sys

from closest import closest_gap

LINE_LIMIT = 200_000


class TooSlow(Exception):
    pass


def run_limited(times):
    """Call closest_gap, but stop it after LINE_LIMIT executed lines: a time limit that is the same everywhere."""
    executed = 0

    def count_lines(frame, event, arg):
        nonlocal executed
        if event == "line":
            executed += 1
            if executed > LINE_LIMIT:
                raise TooSlow
        return count_lines

    sys.settrace(count_lines)
    try:
        return closest_gap(times)
    except TooSlow:
        raise AssertionError(f"too slow: more than {LINE_LIMIT:,} lines ran; every pair is too many at this size") from None
    finally:
        sys.settrace(None)


def test_example():
    """the example from the prompt"""
    assert closest_gap([40, 7, 25, 31]) == 6


def test_shared_time():
    """two readings at the same time are 0 seconds apart"""
    assert closest_gap([5, 90, 5]) == 0


def test_two_readings():
    """the smallest input the limits allow"""
    assert closest_gap([1_000_000_000, 0]) == 1_000_000_000


def test_closest_pair_not_neighbours_in_the_log():
    """the closest pair is far apart in the log"""
    assert closest_gap([100, 50, 0, 75, 101]) == 1


def test_input_unchanged():
    """the caller's list is not changed"""
    times = [40, 7, 25, 31]
    closest_gap(times)
    assert times == [40, 7, 25, 31]


def test_many_readings():
    """20,000 readings within the line limit"""
    rng = random.Random(2026)
    times = rng.sample(range(0, 10**9, 1_000), 20_000)  # all different, all multiples of 1,000
    times[-1] = times[123] + 7  # one pair just 7 seconds apart
    assert run_limited(times) == 7
A hint

The values go up to 10**9, so an array with one slot per second is out, and 200,000 readings rule out every pair. If the times were in order, which readings could be the closest pair? Only certain neighbours need comparing.

The sample tests run on this device, in your browser (Pyodide): nothing is sent to mysmartcopilot.com. The first run downloads Python (about 13.5 MB), which is kept for the next runs. A check in your browser is feedback for you, not proof that the code is right for every input.

Check yourself

7 questions about this lesson. Every answer and why it is right is on the page, behind “Show the answer”. Your score stays in this browser.

  1. Question 1 of 7 Constraints: 1 ≤ n ≤ 2 × 10⁵, time limit 1 second. Which target fits?

    Choose one answer.

    Show the answer to question 1

    Answer: O(n log n) or better

    n² is 4 × 10¹⁰ at the largest n, hundreds of times a budget of about 10⁸ simple steps. n log₂ n is about 3.5 million, which fits easily, even in Python.

  2. Question 2 of 7 Constraints: 1 ≤ n ≤ 20, and you must pick some of the n items. Which target does that suggest?

    Choose one answer.

    Show the answer to question 2

    Answer: O(2ⁿ · n), trying every subset

    2²⁰ is about a million subsets, and checking each one costs about n more steps: about 2 × 10⁷ in all, which fits. 20! is about 2.4 × 10¹⁸, far too many. A limit this small is often a hint that trying every subset is intended.

  3. Question 3 of 7 Constraints: n ≤ 10⁵ numbers and q ≤ 10⁵ queries, each asking for the sum of a range of positions. What should the plan be?

    Choose one answer.

    Show the answer to question 3

    Answer: Prepare once, so that each query costs O(1) or O(log n)

    Scanning for every query costs n × q = 10¹⁰ steps. Preparing once (running totals, for example, which a later module of this track teaches) makes each query a constant amount of work.

  4. Question 4 of 7 n ≤ 10⁵ values, each between 0 and 10⁹. You need to know how often each value appears. What do the limits rule out?

    Choose one answer.

    Show the answer to question 4

    Answer: A list with one counter per possible value, because it would need 10⁹ slots

    A list indexed by value needs a slot for every possible value, a billion of them. A hash map or a sort needs memory only for the values that actually occur.

  5. Question 5 of 7 At about 10⁸ simple steps a second, roughly how many seconds do 10¹⁰ steps take?

    Type a number.

    Show the answer to question 5

    Answer: 100 seconds

    10¹⁰ divided by 10⁸ is 10², so about 100 seconds, against typical limits of a few seconds. That is the cost of an O(n²) algorithm at n = 10⁵.

  6. Question 6 of 7 Up to 10⁴ test cases, and the sum of n over all of them is at most 2 × 10⁵. Which plans fit a budget of about 10⁸ steps?

    Choose every answer that is right.

    Show the answer to question 6

    Answer:

    • O(n log n) work for each test case
    • O(n) work for each test case

    The sum of n is bounded, so work that grows with n adds up to the work for one big test. O(n²) per test fails, because one test case may have n = 2 × 10⁵. Clearing 10⁶ counters 10⁴ times is 10¹⁰ steps, however small the tests are.

  7. Question 7 of 7 A problem says "print the answer modulo 10⁹ + 7". What does that usually tell you?

    Choose one answer.

    Show the answer to question 7

    Answer: The answer is a very large count, usually found by counting with dynamic programming or combinatorics

    Asking for the remainder lets the platform check a count far too large to print in full. It is a hint to count the possibilities rather than list them.

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.