Skip to content

Introduction to DSA with Python

Welcome to the DSA with Python track — a complete, hands-on path from “what is Big-O?” all the way to segment trees and max-flow. It is built for two goals that overlap more than people think:

  • Cracking big-tech interviews (FAANG-style problem solving).
  • Competitive programming (LeetCode, Codeforces, contests).
  • What data structures and algorithms actually are, and why they decide whether your code runs in 0.1 s or times out.
  • How to run and solve problems right here in the browser — no setup.
  • A repeatable way to read a problem, spot the pattern, and reach for the right tool.
  • The full toolkit: arrays → trees → graphs → dynamic programming → advanced CP.

An algorithm is a step-by-step recipe. A data structure is how you organize data so an algorithm can be fast. Pick the wrong structure and even a correct algorithm is too slow to pass.

The same task — “is x in this collection?” — costs wildly different amounts depending on the structure:

StructureMembership checkOrdered?
listO(n)O(n)keeps insertion order
set / dictO(1)O(1) averageno (dict keeps insertion order, set doesn’t)
sorted list + binary searchO(logn)O(\log n)yes

That single choice — list vs set — is the difference between Accepted and Time Limit Exceeded on a large input.

Before any specific data structure, the one picture the whole track is built on: how differently these growth rates behave once the input gets large.

chartWhy the choice of algorithm stops being a matter of tastelog scale, 1e8 op budget
1e11e31e61e91e12judge budget ≈ 1e8 ops1020501001k10k100kO(log n)O(n)O(n log n)O(n²)O(2^n)
budget1e8 ops
setupFive growth rates on a logarithmic vertical axis — linear would flatten everything except the worst curve into a single line at the bottom. The yardstick to hold onto: an online judge accepts roughly 10^8 simple operations, so any curve crossing that line is a time-limit exceeded.
1/9

Step through the n values. At n = 10 every curve is fine and the choice genuinely does not matter; by n = 100000 the quadratic curve is millions of times past the budget line while O(n log n) is comfortable. Everything in this track exists to move a solution from one curve to a lower one.

This track is organized into ordered phases. Follow them top-to-bottom, or jump to a phase you need.

diagram DSA with Python — learning roadmap mermaid

Every code block on this site is live. It runs real Python in your browser (via Pyodide) — click Run to execute, edit the code, and re-run. Try it:

hello_dsa.py
# Edit me, then press Run.
nums = [5, 3, 8, 1, 9, 2]
 
# Two ways to find the max — one is O(n), one hides a sort at O(n log n).
print("max via built-in:", max(nums))
print("sorted[-1]     :", sorted(nums)[-1])

You’ll also see three other block types throughout the track:

  • p5 animation panels — watch an algorithm move (sorting, BFS, DP fills).
  • mermaid diagrams — trees, graphs, and recursion structure.
  • Graded exercises — small tasks that check your answer instantly.

Below is a classic interview warm-up: does the array contain a duplicate? The naive double loop is O(n2)O(n^2). A set makes it O(n)O(n). Fill in the blank to use a set.

You do not need to analyse complexity yet — that is the next page. But two numbers make the rest of this track make sense, so they are worth carrying from the start.

Number one: about 10710^7 simple operations per second in pure Python. (Compiled languages get roughly 10810^8; interpreted loops pay a 10-100x tax.) That single figure is what turns a constraint into a plan:

If the input size isYou can affordWhich usually means
up to ~10anything, including trying every arrangementbrute force
up to ~1,000a nested loop over every pairO(n2)O(n^2)
up to ~100,000one sort, or one pass with a lookup structureO(nlogn)O(n \log n) or O(n)O(n)
up to ~10,000,000a single pass, and not much elseO(n)O(n)
astronomically largeno loop over the input at allmaths, or halving

Number two: the structure you pick changes the class, not just the constant. The same question answered two ways:

“Have I seen this value before?”Cost
Scan a listO(n)O(n) per check — measured 659 µs at n=100,000n = 100{,}000
Ask a setO(1)O(1) per check — measured 0.048 µs, 13,649x faster

Both are one line. Inside a loop, the first makes the whole algorithm O(n2)O(n^2) and the second keeps it O(n)O(n). That gap is what this entire track is about: not writing cleverer code, but choosing the structure whose costs match what you are about to ask of it.

Habits worth avoiding from day one, because they are much harder to unlearn later.

  • Memorising solutions instead of patterns. There are thousands of problems and about thirty patterns. Someone who has memorised 200 solutions is helpless on the 201st; someone who recognises “this is a sliding window” is not.
  • Skipping the brute force. Naming the O(n2)O(n^2) answer takes fifteen seconds and gives you a baseline, a correctness reference, and something to fall back on. Jumping straight to the clever solution means having nothing when it does not work.
  • Reading the solution as soon as it gets hard. Reading is a legitimate way to learn — but log the problem as scheduled, not done, and re-attempt it cold in a week. Understanding a solution and being able to produce one are different skills.
  • Grinding easy problems because they feel productive. Easies drill syntax; mediums drill composition, which is what interviews test. A week that is 80% easy has quietly become a comfort loop.
  • Ignoring the constraints. The constraint block tells you the intended complexity before you have finished reading the statement. Reading it first is the highest-yield habit on this page.
  • Writing code before saying what it will do. In an interview this reads as guessing. Even alone it costs you, because you cannot debug a plan you never articulated.
  • Optimising a solution that is not yet correct. Get it right, then get it fast. An almost-working fast solution is worth nothing.
  • Learning DSA without writing any. Reading about a heap is not the same as having implemented one. Every page in this track has runnable code for that reason.

Not follow-ups to a problem — the questions to ask yourself as you work through this track.

The questionWhy it mattersWhat a good answer looks like
“What pattern is this?”Recognition is the transferable skillName it and the invariant: “sliding window, and the window is valid because all values are positive so the sum is monotonic”
“What is the brute force?”It is your baseline and your fallback“Check every pair, O(n2)O(n^2)” — said before you start optimising, every time
“What does the constraint imply?”It prunes the search space in secondsn12n \le 12 means enumerate; n105n \le 10^5 forbids O(n2)O(n^2); 101810^{18} means no loop over the input at all
“Which structure fits what I am asking?”The choice changes the complexity classMembership -> set. Both ends -> deque. Always-the-smallest -> heap. Key to value -> dict
“Can I state why this is correct?”Correct-looking is not correctAn invariant that holds at every step, or a reason the discarded half cannot contain the answer
“What are the edge cases?”They are where the marks areEmpty, one element, all equal, all negative, and the case the algorithm pivots on
“Did I test it before declaring it done?”Finding your own bug is the strongest signalTrace it by hand on a small input, out loud, before running it
“Could I write this again tomorrow, cold?”The real measure of learningIf not, it is scheduled for re-attempt, not finished
pch.quizTag pch.quizDefaultTitle
  1. Roughly how many simple operations per second should you assume for pure Python?

    pch.quizShowAnswer

    B — About 10^7 -- interpreted loops pay a 10-100x tax, though work pushed into built-ins does not — This one number turns a constraint into a plan: 10^7 per second means n = 100,000 rules out an O(n^2) approach (10^10 operations) but comfortably allows O(n log n). The corollary matters as much -- `sum`, `sorted` and set operations run in C, so expressing a loop as a built-in is often the fix rather than changing the algorithm.

  2. "Have I seen this value before?" -- asked of a list versus a set at n = 100,000. What is the measured difference?

    pch.quizShowAnswer

    B — About 13,649x -- 659 microseconds against 0.048 — Both are one line of code and they differ by four orders of magnitude, because one scans and the other hashes. Inside a loop that is the difference between O(n^2) and O(n). This gap is what the whole track is about: not cleverer code, but structures whose costs match what you are asking of them.

  3. A problem's constraints say n <= 12. What is that telling you?

    pch.quizShowAnswer

    B — That exponential or factorial work is expected -- the setter sized the input for full enumeration — A bound that tiny is never generosity. 2^12 is 4,096 and 12! is about 479 million, so trying every subset or arrangement is exactly what fits. Reading the constraint block before the statement rules out more approaches in five seconds than the prose does in five minutes -- which is the single highest-yield habit in this track.

  4. You read the editorial for a problem you could not solve. How should you record it?

    pch.quizShowAnswer

    B — As scheduled: re-attempt it cold in about a week, because understanding a solution and producing one are different skills — Reading is a legitimate learning move; logging it as done is the mistake, because it removes the problem from your queue without the skill having transferred. If the second attempt a week later is still slow, the pattern has not stuck -- which is precisely the signal a log exists to surface.

  5. Why prefer learning patterns over memorising solutions?

    pch.quizShowAnswer

    B — There are thousands of problems and about thirty patterns -- recognition generalises to problems you have never seen, memorised solutions do not — The arithmetic is the argument. Someone with 200 memorised solutions is stuck on the 201st problem; someone who recognises "contiguous subarray plus an optimum, so sliding window" has a starting point for anything in that family. It is also what makes the constraint-reading habit pay off, since constraints point at patterns rather than at specific answers.

  6. Which structure answers "give me the smallest item, repeatedly" efficiently?

    pch.quizShowAnswer

    B — A heap -- O(log n) push and pop, with the minimum always at the root — Re-sorting after every insertion is O(n^2 log n) overall -- the classic wrong answer here. A set gives O(1) membership but no ordering at all, so it cannot produce the smallest. A deque is O(1) at both ends but only in insertion order. Matching the structure to the *question being asked of it* is the skill this track builds.

Drill 1 — match the need to the structure

Section titled “Drill 1 — match the need to the structure”

Drill 2 — count the operations before you write the code

Section titled “Drill 2 — count the operations before you write the code”
  • About 10710^7 simple operations per second in pure Python (~10810^8 compiled). Do this arithmetic against the constraint before choosing an approach.
  • Read the constraints before the statement. n <= 12 means enumerate; n <= 1000 allows O(n2)O(n^2); n <= 10^5 forbids it.
  • The structure changes the complexity class, not just the constant. x in list is O(n)O(n); x in set is O(1)O(1) — measured 13,649x apart at n=105n = 10^5.
  • Match the structure to the question: membership -> set · both ends -> deque · always-the-smallest -> heap · key to value -> dict · positional -> list.
  • ~30 patterns cover thousands of problems. Learn recognition, not solutions.
  • Always name the brute force first — it is your baseline, your fallback, and your correctness reference.
  • A problem you read the solution to is scheduled, not done. Re-attempt cold in a week.
  • Correct first, then fast. An almost-working fast solution is worth nothing.
  • Write the plan before the code, and test before declaring it finished.
  • Mediums are where interviews live. An 80%-easy week is a comfort loop.
  • Data structure = how data is organized; algorithm = what you do with it.
  • The right structure turns a slow solution into a fast one — often O(n)O(n) vs O(n2)O(n^2).
  • Every code block here is runnable; edit and experiment freely.

Next: Setup for CP & interviews — accounts, tooling, and how to practice.

pch.coffeeTagline

pch.coffeeCta

pch.feedbackHeading

pch.feedbackSubheading