ЁЯПл The SchoolтА║ЁЯзо DSAтА║ЁЯФН рдзрдбрд╛ 08 тАФ Binary search: рдХреНрд░рдорд╛рдиреЗ рд▓рд╛рд╡рд▓реЗрд▓реА рдиреЛрдВрджрд╡рд╣реА
ЁЯЦ╝я╕П See the drawing + lab ЁЯПа Course home ЁЯМ┐ Branch on GitHub тЬПя╕П View source
ЁЯЦ╝я╕П рдЖрдХреГрддреА рдЖрдгрд┐ labThe drawing + lab рдкреВрд░реНрдг рдкрд╛рдирд╛рд╡рд░ рдЙрдШрдбрд╛ тЖЧOpen full page тЖЧ

ЁЯФН рдзрдбрд╛ 08 тАФ Binary search: рдХреНрд░рдорд╛рдиреЗ рд▓рд╛рд╡рд▓реЗрд▓реА рдиреЛрдВрджрд╡рд╣реА

ЁЯУН рддреБрдореНрд╣реА рдЗрдереЗ рдЖрд╣рд╛рдд: 12 рдкреИрдХреА рдзрдбрд╛ 08 ┬╖ рдкреБрдвреЗ: lesson-09-trees-heaps


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

рдзрдбреЗ 01тАУ08. O(log n) рдЪреА рдЪрд╛рд▓, рдкреНрд░рддреНрдпреЗрдХрд╛рдХрдбреВрди рдПрдХрджрд╛ рддрд░реА рдЪреБрдХрдгрд╛рд░рд╛ loop, рдЖрдгрд┐ рдЙрддреНрддрд░рд╛рд╡рд░ binary search рдХрд░рдгреНрдпрд╛рдЪреА рдпреБрдХреНрддреА.

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

рдиреЛрдВрджрд╡рд╣реА рдХреНрд░рдорд╛рдиреЗ рд▓рд╛рд╡рд▓реЗрд▓реА рдЖрд╣реЗ. рддреА рдордзреЛрдордз рдЙрдШрдбрд╛: "Dipika" тАФ рддреБрдордЪреЗ рдирд╛рд╡ рдЖрдзреА рдЖрд╣реЗ рдХреА рдирдВрддрд░? рдЪреБрдХреАрдЪрд╛ рдЕрд░реНрдзрд╛ рднрд╛рдЧ рдлреЗрдХреВрди рджреНрдпрд╛ рдЖрдгрд┐ рдЙрд░рд▓реЗрд▓рд╛ рдЕрд░реНрдзрд╛ рдордзреЛрдордз рдЙрдШрдбрд╛. рдкрдиреНрдирд╛рд╕ рд╣рдЬрд╛рд░ рдирд╛рд╡рд╛рдВрдирд╛ рдЬрд╛рд╕реНрддреАрдд рдЬрд╛рд╕реНрдд рд╕реЛрд│рд╛ рдирдЬрд░рд╛ рд▓рд╛рдЧрддрд╛рдд; рджрд╣рд╛ рд▓рд╛рдЦрд╛рдВрдирд╛ рд╡реАрд╕. рд╣реАрдЪ рдпреБрдХреНрддреА рдиреЛрдВрджрд╡рд╣реА рдЕрдЬрд┐рдмрд╛рдд рдирд╕рд▓реЗрд▓реНрдпрд╛ рдкреНрд░рд╢реНрдирд╛рдВрдЪреАрд╣реА рдЙрддреНрддрд░реЗ рджреЗрддреЗ: "рд╕рдЧрд│реНрдпрд╛ рджрдкреНрддрд░рд╛рдВрдирд╛ рдкреБрд░реЗрд▓ рдЕрд╕рд╛ рд╕рд░реНрд╡рд╛рдд рд▓рд╣рд╛рди locker рдХреЛрдгрддрд╛?" рдПрдХ рдЖрдХрд╛рд░ рдХрд░реВрди рдкрд╛рд╣рд╛ тАФ рдмрд╕рддреЗ? рдордЧ рд▓рд╣рд╛рди рдХрд░реВрди рдкрд╛рд╣рд╛; рдмрд╕рдд рдирд╛рд╣реА? рдореЛрдард╛ рдХрд░реВрди рдкрд╛рд╣рд╛. рдЙрддреНрддрд░ рд╡рд╛рдврддрд╛рдирд╛ рдПрдХрджрд╛рдЪ рдЙрд▓рдЯрдгрд╛рд░рд╛ рдХреЛрдгрддрд╛рд╣реА рд╣реЛ/рдирд╛рд╣реА рдкреНрд░рд╢реНрди рдЕрд╢рд╛ рдкреНрд░рдХрд╛рд░реЗ рд╢реЛрдзрддрд╛ рдпреЗрддреЛ.

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

flowchart LR
  A["lo=0 ┬╖ hi=49,999 ┬╖ mid=24,999"] -->|"target bigger"| B["lo=25,000 ┬╖ hi=49,999"] -->|"target smaller"| C["lo=25,000 ┬╖ hi=37,499"] --> D["тАж 16 looks"]

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

ЁЯдФ рдХрд╛

O(1) рдирдВрддрд░рдЪреА рд╕рд░реНрд╡рд╛рдд рд╕реНрд╡рд╕реНрдд рдЧреЛрд╖реНрдЯ O(log n) рдЖрд╣реЗ, рдЖрдгрд┐ рддреНрдпрд╛рд▓рд╛ рдлрдХреНрдд рдХреНрд░рдо рд▓рд╛рдЧрддреЛ. "scan рдкреЗрдХреНрд╖рд╛ рдЪрд╛рдВрдЧрд▓реЗ рдХрд░рддрд╛ рдпреЗрдИрд▓ рдХрд╛?" рдпрд╛рдЪрд╛ рдЕрд░реНрдзрд╛ рднрд╛рдЧ рдореНрд╣рдгрдЬреЗ "рд╣реЗ sorted рдЖрд╣реЗ рдХрд╛, рдХрд┐рдВрд╡рд╛ рд╣реЛрдК рд╢рдХрддреЗ рдХрд╛?" answer-search рдкреНрд░рдХрд╛рд░ optimisation рдкреНрд░рд╢реНрдирд╛рдВрдЪрд╛ рдПрдХ рдкреВрд░реНрдг рд╡рд░реНрдЧ рддреНрдпрд╛рдЪ рдЖрда рдУрд│реАрдВрдиреА рд╕реЛрдбрд╡рддреЛ.

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

binary_search рдЖрдкрд▓реЗ loops рдореЛрдЬрддреЛ; demo.py search рддреНрдпрд╛рдЪ 50,000 рд╡рд┐рджреНрдпрд╛рд░реНрдереНрдпрд╛рдВрд╡рд░ рддреНрдпрд╛рдЪреНрдпрд╛ 15 рдирдЬрд░рд╛рдВрдЪреА linear search рдЪреНрдпрд╛ 41,235 рд╢реА рддреБрд▓рдирд╛ рдХрд░рддреЛ, рдордЧ fits(cap) check рд╡рд╛рдкрд░реВрди locker capacities 1тАУ240 рд╡рд░ binary search рдХрд░рддреЛ.

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

python3 dsa/demo.py search
python3 - <<'EOF'
import sys, bisect; sys.path.insert(0, "dsa"); from algorithms import binary_search
reg = [3, 7, 7, 7, 12, 20]
print(binary_search(reg, 12), binary_search(reg, 5))                 # (4, steps), (-1, steps)
print("first 7 at", bisect.bisect_left(reg, 7), "┬╖ insert 10 at", bisect.bisect_left(reg, 10))
# search on the answer: the first version where the tests fail
def fails(v): return v >= 137
lo, hi = 1, 1000
while lo < hi:
    mid = (lo + hi) // 2
    if fails(mid): hi = mid
    else: lo = mid + 1
print("first failing version:", lo, "found in ~10 checks")
EOF

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

Linear 41,235 рдирдЬрд░рд╛ рд╡рд┐рд░реБрджреНрдз binary 15 (logтВВ 50,000 тЙИ 15.6); locker рдЪреЗ рдЙрддреНрддрд░ 90 kg; рддреБрдордЪрд╛ bisect рдкрд╣рд┐рд▓рд╛ 7 index 1 рд╡рд░ рдЖрдгрд┐ 10 рд╕рд╛рдареАрдЪрд╛ insertion point index 4 рд╡рд░ print рдХрд░рддреЛ; "first failing version" 137 рдЖрд╣реЗ.

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

рддреБрдореНрд╣реА binary search рдЖрдард╡рдгреАрддреВрди рд▓рд┐рд╣реВ рд╢рдХрддрд╛, рдирд╕рд▓реЗрд▓реА key рд╣рд╛рддрд╛рд│реВ рд╢рдХрддрд╛, рдЖрдгрд┐ рд╣реЛ/рдирд╛рд╣реА рдкреНрд░рд╢реНрдирд╛рдЪреЗ рд╢реЛрдзрддрд╛ рдпреЗрдгрд╛рд▒реНрдпрд╛ range рдордзреНрдпреЗ рд░реВрдкрд╛рдВрддрд░ рдХрд░реВ рд╢рдХрддрд╛.

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

ЁЯПн рдкреНрд░рддреНрдпрдХреНрд╖ рд╡рд╛рдкрд░рд╛рдд рд╣реЗ рдХрд╛ рдорд╣рддреНрддреНрд╡рд╛рдЪреЗ: рдкреНрд░рддреНрдпреЗрдХ database index lookup, рдкреНрд░рддреНрдпреЗрдХ "рдпрд╛ timestamp рд╕рд╛рдареАрдЪрд╛ config рд╢реЛрдзрд╛", рдкреНрд░рддреНрдпреЗрдХ capacity-planning рдордзрд▓рд╛ "рдмрд╕рдгрд╛рд░рд╛ рд╕рд░реНрд╡рд╛рдд рд▓рд╣рд╛рди instance" рдореНрд╣рдгрдЬреЗ binary search тАФ рдмрд╣реБрддреЗрдХ рд╡реЗрд│рд╛ рддреБрдордЪреНрдпрд╛рд╕рд╛рдареА рдХреЗрд▓реЗрд▓рд╛, рдХрдзреАрдХрдзреА рдирд╛рд╣реА.

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

рдзрдбрд╛ 09 тАФ trees рдЖрдгрд┐ heaps: рдХреЕрдЯрд▓реЙрдЧрдЪрд╛ рдЦрдг рдЖрдгрд┐ рд╡реНрдпрд╛рд╕рдкреАрда.

ЁЯФН Lesson 08 тАФ Binary search: the sorted register

ЁЯУН You are here: Lesson 08 of 12 ┬╖ Next: lesson-09-trees-heaps


ЁЯУж What's in this branch

Lessons 01тАУ08. The O(log n) walk, the loop everyone gets wrong once, and the trick of binary-searching an answer.

ЁЯзТ Explain like I'm 5

The register is sorted. Open it in the middle: "Dipika" тАФ is your name before or after? Throw the wrong half away and open the remaining half in the middle. Fifty thousand names take at most sixteen looks; a million take twenty. The same trick answers questions with no register at all: "what is the smallest locker that fits all the bags?" Try a size тАФ does it fit? Then try smaller; doesn't? Try bigger. Any yes/no question that flips once as the answer grows can be searched this way.

ЁЯЧ║я╕П Diagram

flowchart LR
  A["lo=0 ┬╖ hi=49,999 ┬╖ mid=24,999"] -->|"target bigger"| B["lo=25,000 ┬╖ hi=49,999"] -->|"target smaller"| C["lo=25,000 ┬╖ hi=37,499"] --> D["тАж 16 looks"]

тЭУ What

ЁЯдФ Why

O(log n) is the cheapest thing after O(1), and it only needs order. Half of "can we do better than a scan?" is "is it sorted, or could it be?" The answer-search variant solves a whole class of optimisation questions with the same eight lines.

ЁЯФз How (in this repo)

binary_search counts its loops; demo.py search compares its 15 looks with linear search's 41,235 on the same 50,000 pupils, then binary-searches locker capacities 1тАУ240 with a fits(cap) check.

ЁЯзк Try it

python3 dsa/demo.py search
python3 - <<'EOF'
import sys, bisect; sys.path.insert(0, "dsa"); from algorithms import binary_search
reg = [3, 7, 7, 7, 12, 20]
print(binary_search(reg, 12), binary_search(reg, 5))                 # (4, steps), (-1, steps)
print("first 7 at", bisect.bisect_left(reg, 7), "┬╖ insert 10 at", bisect.bisect_left(reg, 10))
# search on the answer: the first version where the tests fail
def fails(v): return v >= 137
lo, hi = 1, 1000
while lo < hi:
    mid = (lo + hi) // 2
    if fails(mid): hi = mid
    else: lo = mid + 1
print("first failing version:", lo, "found in ~10 checks")
EOF

тЬЕ Verify тАФ what you should see

Linear 41,235 looks versus binary 15 (logтВВ 50,000 тЙИ 15.6); the locker answer is 90 kg; your bisect prints the first 7 at index 1 and the insertion point for 10 at index 4; the "first failing version" is 137.

ЁЯПБ What you just proved

You can write binary search from memory, handle the missing key, and turn a yes/no question into a searchable range.

тЪая╕П Common mistakes

ЁЯПн Why this matters in production: every database index lookup, every "find the config for this timestamp", every capacity-planning "smallest instance that fits" is binary search тАФ usually done for you, sometimes not.

тПня╕П Next

Lesson 09 тАФ trees & heaps: the catalogue drawer and the podium.

тЖР PrevioussortingNext тЖТtrees heaps

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