Dinesh/ Blog
algorithms

Algorithm practice · From recognition to a defensible solution

A broad problem-family route alongside the runnable Foundations Lab: derive invariants, study variants, test with oracles and track specific gaps.

22 min readChecking device speech…
Lesson preparation & details

Level: beginner

By the end, you should be able to

  • Practice an algorithm without confusing recall with proof
  • Choose a data structure from its contract
  • Record a concrete gap and a regression test

Sources checked: . A source check does not change the publication or update date.

Editorial review: · What review means

In this article · 14 sections

This route combines 65 problem-family and practice lessons, a variant-contract supplement and a smaller runnable Foundations Lab. The family lessons preserve breadth; the lab teaches how to compose a few mechanisms into one system. Neither is a guarantee of interview readiness. Timers are optional practice conventions, not universal hiring requirements, and each lesson names its actual review and execution limits.

Algorithm practice needs both knowledge and execution. Recognizing a familiar shape can help you start, but naming “sliding window” does not establish nonnegativity, naming “heap” does not define tie-breaking, and naming “DP” does not supply a sufficient state. The useful habit is to turn recognition into a contract and a correctness argument.

A focused practice map

  1. Contracts: wrong types, aliasing, mutation and exception boundaries.
  2. Counts and prefixes: retain only the information the query needs; compare with enumeration.
  3. Search and windows: justify each discarded candidate and test the broken assumption.
  4. Frontiers: use LIFO, FIFO or priority order intentionally; account for each push and pop.
  5. Graphs: shortest hops differ from dependency readiness; edge direction is an interface decision.
  6. Dynamic programming: define state, transitions, order and base cases before compressing storage.

These pages form the compact Foundations Lab. They do not replace advanced string algorithms, segment trees, weighted shortest paths or specialized dynamic-programming families. The broader route below gives those subjects separate lessons and states their assumptions; code execution is recorded separately from conceptual explanation.

A session that produces evidence

Choose one problem and write five things before optimizing:

  • Contract: inputs, outputs, invalid cases, duplicate policy and mutation policy.
  • Oracle: a straightforward small-input solution you can inspect.
  • State: what each data structure or DP cell means.
  • Argument: initialization, preservation and termination—or a recurrence and dependency-order justification.
  • Cost: number of operations, representation assumptions and additional storage.

Then implement the improvement and compare it with the oracle. After a failure, classify the mistake: misunderstood contract, insufficient state, invalid discard, wrong implementation, or incorrect cost model. “I missed the pattern” is only one possible explanation, not the whole post-mortem.

A timer is optional. If you use one, budget the activities honestly: 5 minutes contract, 10 oracle and derivation, 20 implementation, 15 testing, 10 review is 60 minutes, excluding breaks. This is a suggested practice format, not a researched optimal schedule or a guarantee that a hard problem will fit. Stop and split the task when it does not.

A small diagnostic, fully worked

A sorted list can answer whether a value exists through lower-bound search. The official bisect documentation is explicit: the function returns an insertion point, not necessarily an equality match. Convert that insertion point into membership without indexing past the end.

from bisect import bisect_left
from itertools import combinations_with_replacement
 
 
def contains_sorted(values, target):
    i = bisect_left(values, target)
    return i < len(values) and values[i] == target
 
for n in range(7):
    for values in combinations_with_replacement(range(4), n):
        for target in range(-1, 5):
            assert contains_sorted(values, target) == (target in values)
assert not contains_sorted([], 1)
assert not contains_sorted([1, 3], 4)
assert contains_sorted([1, 3, 3], 3)

The insertion boundary may equal the length, so check the bound before indexing. Short-circuit and ensures the second expression is not evaluated when the first is false. Sortedness is a precondition, not a fact established by this function. The comparison count is O(log n) under random access and bounded comparison cost; sorting an unsorted input first is separate work. The oracle's linear membership test is intentionally simpler.

Passing the test shows agreement on the enumerated arrays and targets. The all-input argument comes from the partition contract: before the insertion point values are too small; at that point either the target matches or the first not-smaller value is already too large.

Exercises

  1. Remove the bounds check. Find the smallest failing input, then keep it as a regression case.
  2. Change the contract from “exists” to “how many occurrences.” What boundary pair is useful?
  3. You reproduced the function from memory, but cannot explain why sortedness matters. Is the topic complete?
Answer sketches
  1. Empty input is enough: indexing position zero fails. A target larger than every element also returns the length.
  2. Subtract bisect_left from bisect_right; the latter inserts after equal values. Both require the same sorted ordering contract.
  3. No. Explain how sortedness lets a comparison rule out an entire side; then supply an unsorted counterexample. Recall is useful evidence of recall, not of the discard argument.

Keep a gap log, not a verdict about yourself

Record the failing input, violated assumption, repair and a later re-solve date you can actually honor. Revisit a mix of recent failures and older material. The intervals are your adjustable study policy, not universal scientifically validated constants. Do not retain unsupported claims that a fixed number of patterns explains all problems, a particular company always asks a particular question, or timed performance follows automatically from finishing a list.

For a larger assessment, complete the local notebook capstone. Its rubric asks you to compose algorithms with data and failure boundaries. An interview problem usually omits some of those concerns; a production service adds many more. Neither setting is fully represented by a practice score.

Return to the full Foundations Lab map for SQL, retries and bounded-work lessons.

Restored problem-family route

The compact Foundations Lab remains intact. It is a runnable core, not a replacement for the broader subjects below. Use the focused family lessons for derivations, variants, failure cases and practice.

Why this exists

A concept lesson can explain a heap without supplying enough varied practice to choose and implement one in a new problem. This route therefore develops both reasoning and execution. Algorithmic problem solving is not simply a motor skill: recognizing a pattern, deriving a valid state, writing code and checking an argument are different tasks. Typing practice alone does not supply correctness.

There is no supported comparison here showing that 150 grouped problems beat 500 random problems, or that everyone becomes interview-ready after 65 sessions. Use the broad curriculum to acquire methods, then assess transfer with mixed unfamiliar tasks. The Foundations Lab remains a complementary composition project, not the entire algorithm curriculum.

The core idea: patterns, not problems

A pattern is a proved decision rule under a stated contract, not a keyword-to-template lookup. Sortedness licenses particular two-pointer eliminations; nonnegative values license a standard minimum-sum window; a sufficient state licenses memoization. Practice recognition, then derive the invariant and test its assumptions. There is no universal count of thirty keys or a guarantee of classification in sixty seconds.

For “longest substring with at most K distinct characters,” adding a character can violate a frequency-map constraint and shrinking restores it. For “shortest subarray with sum at least S,” the usual shrink-while-valid procedure relies on nonnegative numbers. With [1, -1, 3] and target 3, that procedure can report length 3 and miss [3]: after removing the first 1 it stops at sum 2, although removing -1 would make the suffix valid again. The shared expand/shrink shape does not make the contracts interchangeable. Negative inputs need a different argument, such as prefixes plus a monotonic deque.

Think of a key ring only as a mnemonic: a key’s label is not evidence it fits the lock. Time pressure can reward practiced methods, but derivation, adaptation and communication remain important; interviews and design reviews do not all have a twenty-minute format. Start with grouped worked examples, then mix families after you understand them so the section title no longer gives away the answer.

How a session runs

For a 75-minute optional format, use 5 minutes blank-file warm-up, 10 pattern anatomy, 15 guided solve, 25 solo attempt, 10 post-mortem and 10 spaced review. The original 5+10+15+30+10+10 proposal actually totaled 80 minutes; this corrected agenda totals 75. One guided and one solo problem plus later review may be enough. Five supplied variants are not five completed independent solves.

During warm-up, reconstruct the state and invariant, not only syntax. In anatomy, ask which inputs invalidate the method. Narrate the guided example, then attempt a different instance without its solution. Record contract, state, implementation and cost errors in the post-mortem, not just a missed cue. A due review should come from recorded dates and earlier failures rather than a claim that an automatic calendar already exists.

The 60-minute evidence session earlier on this page is an alternative, not extra work added to this 75-minute session. To fit 65 sessions in 26 weeks, alternate three-session and two-session weeks; every other calendar day would yield about 91 sessions instead. Choose morning or evening from real availability. Extend the plan when the queue or difficulty exceeds capacity.

The two-attempt rule

Use one consistent optional policy: try unaided for up to 15 minutes, take a small hint if needed, then allow up to 10 further minutes. If still stuck, read the worked answer, close it and reconstruct with feedback. Retest around two days later or at the next feasible review slot. A hint-assisted solution is not an unaided success; a pattern-name hint may supply exactly the selection skill you wanted to assess.

The rule limits unproductive struggle, not the permitted number of attempts. A third attempt is useful when recorded honestly. Copying can help inspect a reference implementation, but copy-and-submit alone provides no evidence that you can derive it. A learner who lacks prerequisite syntax needs instruction, not an enforced period of frustration. These times are conventions, not experimentally established optima.

Spaced repetition, concretely

Record problem, failed assumption, correction, attempt type and an actual retest date. Illustrative queue labels are cold (unaided and justified; up to +60 days), warm (slow/error-repaired; +21), hint (+7), and failed (worked answer needed; +2 after correction). Treat the intervals as adjustable defaults, not universal constants. A familiar success does not justify delaying all unseen variants for 60 days; on overload, prioritize and explicitly reschedule rather than silently drop the queue.

Roediger and Karpicke (2006) found a delayed retention advantage for prior tests in prose learning, even though immediate restudy performance and confidence could be higher. Cepeda et al. (2006) found interacting study-gap and retention-delay effects in verbal recall. Neither paper establishes a coding calendar, motor-memory model or hiring outcome.

Breadth supplies novel variants but can leave shallow understanding when never revisited. Repeated depth can improve accessibility but overfit familiar examples if the cue always names the method. Combine supported initial learning, spaced reconstruction and mixed transfer. Do not claim that skipping one queue destroys a session’s learning or that random problems are never useful.

The five phases

The source directory contains exactly 65 numbered lessons: 6 + 26 + 12 + 12 + 9. The read-only site graph uses editorial plan/order edges separately from prerequisites, and the variant-contract supplement is an extra lesson—not number 66 in the original route. Existence and publication metadata do not substitute for each lesson’s substantive evidence.

  1. Phase 0, L01–L06 (6): problem contracts, operation counts, Python idioms, mutation, hashing and UMPIRE. Advance when you can state a baseline, input assumptions, oracle and cost model.
  2. Phase 1, L07–L32 (26): two pointers, three window variants, prefixes, three search variants, stacks/deques, lists, recursion, tree traversal/BST/path problems, heaps, graph traversal/shortest hops/topological order/DSU and backtracking. Advance by explaining each discard or frontier rule and finding a broken-precondition case; no unsupported “80% of interviews” statistic is needed.
  3. Phase 2, L33–L44 (12): overlapping subproblems, linear and take/skip states, LIS/LCS, single-use and reusable knapsack, grids, edit distance, palindromes, interval DP, state machines and bitmasks. Derive recursion, memo keys and dependency order before compressing storage; reconstruct a solution when the contract asks for one.
  4. Phase 3, L45–L56 (12): tries, bits, number theory, intervals, greedy proofs, matrices, composed O(1)/stream structures, comparators, segment/Fenwick trees, string matching and weighted graph algorithms. Test the assumptions behind the complexity claim and compare with a simpler small-input oracle.
  5. Phase 4, L57–L65 (9): mixed mocks, narration, gap audit, weak-pattern repair, hard decomposition, company-tagged transfer, senior-style composition, contest and maintenance. Use a consistent scoring rubric across attempts; a company label is neither a prediction nor a privileged question list.

The variant-contract supplement adds bounded copies, two budgets, cut reconstruction and subset routes without replacing individual DP lessons. Keep it after the prerequisites its actual tasks need, rather than treating graph adjacency as proof of conceptual readiness.

What done looks like

For an unfamiliar task, state a complete contract, supply a valid invariant/recurrence, justify cost including Python allocations, pass ordinary and boundary checks, and adapt to one changed assumption. A 45-minute Medium/Hard mock is an optional diagnostic; finishing the route does not guarantee that outcome or production readiness.

Use a concrete exit rubric: explain without notes; implement against an independent small oracle; find a counterexample to an invalid variant; and reproduce the reasoning after a delay. If recall succeeds but proof fails, record a proof gap. If the proof is right but code fails, keep the failing input. Do not convert page visits, compile success or a solved count into a mastery claim.

The original six takeaways remain, with corrected boundaries: practice reasoning as well as execution; group initially and mix later; reconstruct before consulting notes when prerequisites permit; label hints and retest; retain a specific failed assumption and regression test; and use a manageable queue rather than guaranteed consolidation claims.

Corrective source notes

The primary research links above support bounded learning claims, not exact review intervals. The Python 3.12 bisect contract supports the protected lower-bound example; its exact code was retained and rerun. The 65 source destinations and the current graph/metadata were inventoried read-only on 2026-10-08. This hub review certifies its explanations and navigation inventory, not a new review of every linked lesson or an application release.

Pause / Recall / Apply

Can you explain it without the page?

Close the example. Reconstruct the core idea, then change one assumption. Mark complete when you’re ready; you can always undo it.

Stored in this browser only. No account, no sync. Clearing browser data removes your record.