ЁЯПл The SchoolтА║ЁЯзо DSAтА║ЁЯУП рдзрдбрд╛ 01 тАФ DSA рдХрд╛ рдЖрдгрд┐ Big-O: рд╢рд╛рд│рд╛ рджреБрдкреНрдкрдЯ рдЭрд╛рд▓реНрдпрд╛рд╡рд░ рдХрд╛рдо рдХрд╕реЗ рд╡рд╛рдврддреЗ
ЁЯЦ╝я╕П See the drawing + lab ЁЯПа Course home ЁЯМ┐ Branch on GitHub тЬПя╕П View source
ЁЯЦ╝я╕П рдЖрдХреГрддреА рдЖрдгрд┐ labThe drawing + lab рдкреВрд░реНрдг рдкрд╛рдирд╛рд╡рд░ рдЙрдШрдбрд╛ тЖЧOpen full page тЖЧ

ЁЯУП рдзрдбрд╛ 01 тАФ DSA рдХрд╛ рдЖрдгрд┐ Big-O: рд╢рд╛рд│рд╛ рджреБрдкреНрдкрдЯ рдЭрд╛рд▓реНрдпрд╛рд╡рд░ рдХрд╛рдо рдХрд╕реЗ рд╡рд╛рдврддреЗ

ЁЯУН рддреБрдореНрд╣реА рдЗрдереЗ рдЖрд╣рд╛рдд: 12 рдкреИрдХреА рдзрдбрд╛ 01 ┬╖ рдкреБрдвреЗ: lesson-02-arrays


ЁЯУж рдпрд╛ рдмреНрд░рдБрдЪрдордзреНрдпреЗ рдХрд╛рдп рдЖрд╣реЗ

рдкреНрд░рддреНрдпреЗрдХ data structure рдЖрдгрд┐ рдкреНрд░рддреНрдпреЗрдХ algorithm рдЬреНрдпрд╛ рдПрдХрд╛ рдкреНрд░рд╢реНрдирд╛рд╡рд░ рддрдкрд╛рд╕рд▓рд╛ рдЬрд╛рддреЛ рддреЛ рдкреНрд░рд╢реНрди: input рджреБрдкреНрдкрдЯ рдЭрд╛рд▓рд╛ рдХреА рдХрд╛рдо рдХрд╕реЗ рд╡рд╛рдврддреЗ? рд╕рдВрдкреВрд░реНрдг рдХреЛрд░реНрд╕рднрд░ рддреБрдореНрд╣реА рд╡рд╛рдкрд░рд╛рд▓ рддреНрдпрд╛ рдЦрд▒реНрдпрд╛ files:

ЁЯОТ рд╕реБрд░реВ рдХрд░рдгреНрдпрд╛рдЖрдзреА: рддреБрдореНрд╣рд╛рд▓рд╛ рдлрдХреНрдд Python 3 рд▓рд╛рдЧреЗрд▓, рдмрд╛рдХреА рдХрд╛рд╣реА рдирд╛рд╣реА. Loops, lists рдЖрдгрд┐ functions рдкреБрд░реЗрд╕реЗ рдЖрд╣реЗрдд. рдЪрд╛рдВрдЧрд▓реЗ рд╢реЗрдЬрд╛рд░реА: Database school (indexes рдореНрд╣рдгрдЬреЗ disk рд╡рд░рдЪреЗ рдзрдбрд╛ 09 рдЪреЗ trees) рдЖрдгрд┐ Networking school (routing рдореНрд╣рдгрдЬреЗ рдзрдбрд╛ 10 рдЪреЗ graphs).

ЁЯзТ 5 рд╡рд░реНрд╖рд╛рдВрдЪреНрдпрд╛ рдореБрд▓рд╛рд▓рд╛ рд╕рдордЬрд╛рд╡рд▓реНрдпрд╛рд╕рд╛рд░рдЦреЗ

рд╢рд╛рд│реЗрдд 1,000 рд╡рд┐рджреНрдпрд╛рд░реНрдереА рдЖрд╣реЗрдд рдЖрдгрд┐ рдПрдХ рдиреЛрдВрджрд╡рд╣реА рдЖрд╣реЗ. "Dipika" рд╢реЛрдзрд╛рдпрд▓рд╛ рддреБрдореНрд╣реА рд╡рд░реВрди рд╡рд╛рдЪреВ рд╢рдХрддрд╛ тАФ рд╕рд░рд╛рд╕рд░реА 500 рдирд╛рд╡реЗ. рдкреБрдврдЪреНрдпрд╛ рд╡рд░реНрд╖реА рд╢рд╛рд│рд╛ рджреБрдкреНрдкрдЯ рд╣реЛрддреЗ: рд╕рд░рд╛рд╕рд░реА 1,000 рдирд╛рд╡реЗ. рд╣реЗ O(n): рд╢рд╛рд│рд╛ рджреБрдкреНрдкрдЯ, рдХрд╛рдо рджреБрдкреНрдкрдЯ.

рдиреЛрдВрджрд╡рд╣реА рдХреНрд░рдорд╛рдиреЗ рд▓рд╛рд╡рд▓реЗрд▓реА рдЕрд╕реЗрд▓ рддрд░ рддреА рдордзреЛрдордз рдЙрдШрдбрд╛: "Dipika" рдЖрдзреА рдЖрд╣реЗ рдХреА рдирдВрддрд░? рдЕрд░реНрдзреА рдлреЗрдХреВрди рджреНрдпрд╛, рдкреБрдиреНрд╣рд╛ рдХрд░рд╛ тАФ 1,000 рдирд╛рд╡рд╛рдВрд╕рд╛рдареА рджрд╣рд╛ рдирдЬрд░рд╛, 2,000 рд╕рд╛рдареА рдЕрдХрд░рд╛. рд╣реЗ O(log n): рд╢рд╛рд│рд╛ рджреБрдкреНрдкрдЯ, рдлрдХреНрдд рдПрдХ рдирдЬрд░ рдЬрд╛рд╕реНрдд.

рдкреНрд░рддреНрдпреЗрдХ рд╡рд┐рджреНрдпрд╛рд░реНрдереНрдпрд╛рдЪрд╛ рдПрдХ рдХрдкреНрдкрд╛ рдЕрд╕реЗрд▓ рдЖрдгрд┐ рдирд╛рд╡рд╛рд╡рд░реВрди рдХреЛрдгрддрд╛ рдХрдкреНрдкрд╛ рддреЗ рдореЛрдЬрддрд╛ рдпреЗрдд рдЕрд╕реЗрд▓, рддрд░ рдЖрдХрд╛рд░ рдХрд┐рддреАрд╣реА рдЕрд╕реЛ, рдПрдХрдЪ рдирдЬрд░: O(1).

Big-O рдореНрд╣рдгрдЬреЗ рддреНрдпрд╛ рд╡рд╛рдвреАрдЪрд╛ рдЖрдХрд╛рд░. рд╕реЗрдХрдВрдж рдирд╛рд╣реА, computer рдирд╛рд╣реА тАФ рдлрдХреНрдд рдЖрдХрд╛рд░. рдХреЛрдгрддреНрдпрд╛рд╣реА loop рдЪрд╛ рдЖрдХрд╛рд░ рджрд┐рд╕реВ рд▓рд╛рдЧрд▓рд╛ рдХреА рдпреЛрдЧреНрдп structure рдмрд╣реБрддреЗрдХ рд╡реЗрд│рд╛ рдЖрдкреЛрдЖрдк рдирд┐рд╡рдбрд▓рд╛ рдЬрд╛рддреЛ.

ЁЯЧ║я╕П рдЖрдХреГрддреА

flowchart LR
  A["n = 1,000"] -->|"├Ч2"| B["n = 2,000"]
  B --> C["O(1): same ┬╖ O(log n): +1 ┬╖ O(n): ├Ч2 ┬╖ O(n log n): ├Ч2.1 ┬╖ O(n┬▓): ├Ч4 ┬╖ O(2тБ┐): squared"]

тЭУ рдХрд╛рдп

рдЖрдХрд╛рд░ рдирд╛рд╡ input рджреБрдкреНрдкрдЯ рдХреЗрд▓рд╛ тЖТ рдЙрджрд╛рд╣рд░рдг
O(1) constant рддреЗрд╡рдвреЗрдЪ lockers[17], d[key], push/pop
O(log n) logarithmic +1 step binary search, balanced tree, heap push
O(n) linear ├Ч2 list scan рдХрд░рдгреЗ, рд╢рдмреНрдж рдореЛрдЬрдгреЗ
O(n log n) linearithmic ├Ч2 рдЖрдгрд┐ рдереЛрдбреЗ рдЬрд╛рд╕реНрдд merge sort, sorted()
O(n┬▓) quadratic ├Ч4 loop рдЪреНрдпрд╛ рдЖрдд loop, bubble sort
O(2тБ┐) exponential рд╡рд░реНрдЧ (squared) рд╕рд╛рдзрд╛ fib, рдкреНрд░рддреНрдпреЗрдХ subset рдХрд░реВрди рдкрд╛рд╣рдгреЗ

ЁЯдФ рдХрд╛

рдкрд╣рд╛рдЯреЗ 3 рд╡рд╛рдЬрддрд╛ рдпреЗрдгрд╛рд░рд╛ page рдмрд╣реБрддреЗрдХ рд╡реЗрд│рд╛ рдЖрдХрд╛рд░рд╛рдЪрд╛ рдкреНрд░рд╢реНрди рдЕрд╕рддреЛ: рджрд╣рд╛ рд▓рд╛рдЦ rows рд╡рд░ nested loop (n┬▓), loop рдордзреНрдпреЗ list.pop(0) (рдкреНрд░рддреНрдпреЗрдХ pop рд▓рд╛ n), dict рд╣рд╡рд╛ рд╣реЛрддрд╛ рддрд┐рдереЗ рдХреЗрд▓реЗрд▓рд╛ lookup. рдореБрд▓рд╛рдЦрддреАрдВрдордзреНрдпреЗ рд╣реЗ рд╡рд┐рдЪрд╛рд░рддрд╛рдд рдХрд╛рд░рдг production рдпрд╛рдЪреЗрдЪ рдмрдирд▓реЗрд▓реЗ рдЕрд╕рддреЗ.

ЁЯФз рдХрд╕реЗ (рдпрд╛ repo рдордзреНрдпреЗ)

demo.py bigo 1k, 10k рдЖрдгрд┐ 100k рд╡рд┐рджреНрдпрд╛рд░реНрдереНрдпрд╛рдВрдЪреА рдиреЛрдВрджрд╡рд╣реА рдмрдирд╡рддреЛ рдЖрдгрд┐ рд╢реЗрд╡рдЯрдЪрд╛ рд╡рд┐рджреНрдпрд╛рд░реНрдереА рддреАрди рдкреНрд░рдХрд╛рд░реЗ рд╢реЛрдзрддреЛ тАФ linear, binary, hash тАФ рдЖрдгрд┐ рдкреНрд░рддреНрдпреЗрдХрд╛рд╕рд╛рдареА steps рдЖрдгрд┐ milliseconds print рдХрд░рддреЛ. step counts functions рдордзреВрдирдЪ рдпреЗрддрд╛рдд.

ЁЯзк рдХрд░реВрди рдкрд╛рд╣рд╛

python3 dsa/demo.py bigo
python3 dsa/test_dsa.py
python3 - <<'EOF'
import time
for n in (10_000, 20_000, 40_000):
    xs = list(range(n)); t = time.perf_counter()
    pairs = sum(1 for i in range(n) for j in range(i + 1, n, 97))   # a thinned n┬▓ loop
    print(n, f"{(time.perf_counter() - t) * 1000:.0f} ms")           # watch it ├Ч4 each time n doubles
EOF

тЬЕ рддрдкрд╛рд╕рд╛ тАФ рддреБрдореНрд╣рд╛рд▓рд╛ рдХрд╛рдп рджрд┐рд╕рд╛рдпрд▓рд╛ рд╣рд╡реЗ

Linear steps 1,000 тЖТ 10,000 тЖТ 100,000 рдЕрд╕реЗ рд╡рд╛рдврддрд╛рдд (рдкреНрд░рддреНрдпреЗрдХ рд╡реЗрд│реА ├Ч10); binary steps 10 тЖТ 14 тЖТ 17 (рдкреНрд░рддреНрдпреЗрдХ ├Ч10 рд▓рд╛ рд╕реБрдорд╛рд░реЗ +3); hash 1 рд╡рд░рдЪ рд░рд╛рд╣рддреЛ. n рджреБрдкреНрдкрдЯ рдЭрд╛рд▓рд╛ рдХреА n┬▓ loop рдЪрд╛ рд╡реЗрд│ рд╕рд╛рдзрд╛рд░рдг рдЪрд╛рд░рдкрдЯ рд╣реЛрддреЛ. test_dsa.py OK print рдХрд░рддреЛ.

ЁЯПБ рддреБрдореНрд╣реА рдЖрддреНрддрд╛рдЪ рдХрд╛рдп рд╕рд┐рджреНрдз рдХреЗрд▓реЗ

Big-O рдбреЛрд│реНрдпрд╛рдВрдирд╛ рджрд┐рд╕рддреЛ: рддреБрдореНрд╣реА рд╕реНрд╡рддрдГрдЪреНрдпрд╛ machine рд╡рд░ рддреАрди рдЖрдХрд╛рд░ рд╡рд╛рдврддрд╛рдирд╛ рдкрд╛рд╣рд┐рд▓реЗ рдЖрдгрд┐ рдкреНрд░рддреНрдпреЗрдХрд╛рд▓рд╛ рддреНрдпрд╛рдЪреНрдпрд╛ рд╡рд╛рдЧрдгреНрдпрд╛рд╡рд░реВрди рдирд╛рд╡ рджреЗрдК рд╢рдХрддрд╛.

тЪая╕П рдиреЗрд╣рдореАрдЪреНрдпрд╛ рдЪреБрдХрд╛

ЁЯПн рдкреНрд░рддреНрдпрдХреНрд╖ рд╡рд╛рдкрд░рд╛рдд рд╣реЗ рдХрд╛ рдорд╣рддреНрддреНрд╡рд╛рдЪреЗ: рдкреНрд░рддреНрдпреЗрдХ scaling incident рдореНрд╣рдгрдЬреЗ рдЕрд╕рд╛ рдЖрдХрд╛рд░ рдЬреЛ n = 1,000 рд▓рд╛ рдареАрдХ рд╣реЛрддрд╛ рдЖрдгрд┐ n = 1,000,000 рд▓рд╛ рдШрд╛рддрдХ рдард░рд▓рд╛. ship рдХрд░рдгреНрдпрд╛рдЖрдзреА рдЖрдХрд╛рд░рд╛рд▓рд╛ рдирд╛рд╡ рджреЗрдгреЗ рд╣реЗ рд╕рд░реНрд╡рд╛рдд рд╕реНрд╡рд╕реНрдд performance рдХрд╛рдо рдЖрд╣реЗ.

тПня╕П рдкреБрдвреЗ

рдзрдбрд╛ 02 тАФ arrays рдЖрдгрд┐ strings: рд▓реЙрдХрд░реНрд╕рдЪреА рд░рд╛рдВрдЧ, рдЖрдгрд┐ рд╡рд╛рдЪрдгреЗ рдЬрд▓рдж рдкрдг рдордзреЗ рд╡рд╛рдврд╡рдгреЗ рдХрд╛ рдЬрд▓рдж рдирд╛рд╣реА.

ЁЯУП Lesson 01 тАФ Why DSA & Big-O: how the work grows when the school doubles

ЁЯУН You are here: Lesson 01 of 12 ┬╖ Next: lesson-02-arrays


ЁЯУж What's in this branch

The one question every data structure and every algorithm is answered by: how does the work grow when the input doubles? Real files you will use all the way through:

ЁЯОТ Before you start: you need Python 3 and nothing else. Loops, lists and functions are enough. Good neighbours: the Database school (indexes are lesson 09's trees on disk) and the Networking school (routing is lesson 10's graphs).

ЁЯзТ Explain like I'm 5

The school has 1,000 pupils and one register. To find "Dipika" you could read from the top тАФ on average 500 names. Next year the school doubles: 1,000 names on average. That is O(n): double the school, double the work.

If the register is sorted, open it in the middle: is "Dipika" before or after? Throw half away, repeat тАФ ten looks for 1,000 names, eleven for 2,000. That is O(log n): double the school, one more look.

If every pupil has a pigeonhole and you can compute which one from the name, it is one look whatever the size: O(1).

Big-O is the shape of that growth. Not the seconds, not the computer тАФ the shape. Once you can see the shape of any loop, the right structure usually picks itself.

ЁЯЧ║я╕П Diagram

flowchart LR
  A["n = 1,000"] -->|"├Ч2"| B["n = 2,000"]
  B --> C["O(1): same ┬╖ O(log n): +1 ┬╖ O(n): ├Ч2 ┬╖ O(n log n): ├Ч2.1 ┬╖ O(n┬▓): ├Ч4 ┬╖ O(2тБ┐): squared"]

тЭУ What

Shape Name Double the input тЖТ Example
O(1) constant same lockers[17], d[key], push/pop
O(log n) logarithmic +1 step binary search, balanced tree, heap push
O(n) linear ├Ч2 scan a list, count words
O(n log n) linearithmic ├Ч2 and a bit merge sort, sorted()
O(n┬▓) quadratic ├Ч4 a loop inside a loop, bubble sort
O(2тБ┐) exponential squared naive fib, trying every subset

ЁЯдФ Why

A page at 3 a.m. is usually a shape problem: a nested loop over a million rows (n┬▓), a list.pop(0) in a loop (n per pop), a lookup that should have been a dict. Interviews ask about it because production is made of it.

ЁЯФз How (in this repo)

demo.py bigo builds a register of 1k, 10k and 100k pupils and finds the last one three ways тАФ linear, binary, hash тАФ printing steps and milliseconds for each. The step counts come from the functions themselves.

ЁЯзк Try it

python3 dsa/demo.py bigo
python3 dsa/test_dsa.py
python3 - <<'EOF'
import time
for n in (10_000, 20_000, 40_000):
    xs = list(range(n)); t = time.perf_counter()
    pairs = sum(1 for i in range(n) for j in range(i + 1, n, 97))   # a thinned n┬▓ loop
    print(n, f"{(time.perf_counter() - t) * 1000:.0f} ms")           # watch it ├Ч4 each time n doubles
EOF

тЬЕ Verify тАФ what you should see

Linear steps grow 1,000 тЖТ 10,000 тЖТ 100,000 (├Ч10 each time); binary steps 10 тЖТ 14 тЖТ 17 (about +3 per ├Ч10); hash stays at 1. The n┬▓ loop's time roughly quadruples when n doubles. test_dsa.py prints OK.

ЁЯПБ What you just proved

Big-O is visible: you watched three shapes grow on your own machine and can name each one from its behaviour.

тЪая╕П Common mistakes

ЁЯПн Why this matters in production: every scaling incident is a shape that was fine at n = 1,000 and fatal at n = 1,000,000. Naming the shape before shipping is the cheapest performance work there is.

тПня╕П Next

Lesson 02 тАФ arrays & strings: the row of lockers, and why reading is fast but growing in the middle is not.

тЖР Course homeall lessonsNext тЖТarrays

This page is the lesson's README from the lesson-01-why-dsa branch, shown here so the whole School stays on one site. Code files open on GitHub at the same branch.