3.7.7 · D1 · Coding › Algorithm Paradigms › Memoization (top-down DP) — recursive + memo dict
Memoization bas saadi recursion hai jiske paas ek notebook hai : jab bhi woh kisi problem ke ek chhote piece ka answer nikaalti hai, woh usse likh leti hai taaki us kaam ko dobara kabhi na karna pade. Is page par jo bhi hai woh ek sentence kamaaने ke liye hai — "har distinct subproblem ko exactly ek baar solve karo, yaad rakho, aur reuse karo."
Yeh page self-contained hai: yeh har symbol aur idea ko zero se build karti hai, isliye tum isse akele padh sakte ho. Jahan koi word bahar link karta hai (jaise Recursion ), woh link baad mein gehraai mein jaane ki jagah hai — tumhe yeh page follow karne ke liye iska zarurat nahin hai. Ant mein tumhare paas "Memoization" topic ke liye poora mental toolkit hoga.
Recall Woh "parent topic" kya hai jiske baare mein main sunta rehta hoon?
Yeh page ek foundations companion hai ek main topic note ke saath jiska naam hai Memoization (top-down DP) . Woh main note in ideas ko real problems par apply karta hai. Jo kuch bhi memoization ko samajhne ke liye chahiye woh sab yahan define hai — main note woh jagah hai jahan tum isse use karoge.
Poora topic ek idea ke upar tikaa hai: ek rule jo apne aap ke terms mein likha hota hai.
Ek function ek machine hai: tum kuch andar daalo (woh input hai) aur ek cheez bahar aati hai (woh output hai). Hum fib(5) likhte hain matlab "machine fib ko input 5 par chalaao."
Tasveer: ek box jisme ek arrow andar jaata hai (5 label ke saath) aur ek arrow bahar aata hai (answer label ke saath).
Recursion tab hoti hai jab ek function ka rule khud ko ek chhote input par use karta hai. Ek bade sawaal ka jawaab dene ke liye, woh usi sawaal ko ek chhote piece ke baare mein poochhta hai, aur tab tak chhotaa karta rehta hai jab tak piece itna chhota na ho jaaye ki jawaab obvious ho.
Neeche di gayi tasveer dekho. fib(5) tak pahunchne ka matlab hai pehle fib(4) aur fib(3) tak pahunchna. Woh aage split hote hain. Splitting sirf neeche rukti hai, jahan answer ke liye aur koi kaam nahin chahiye.
Mote double border waale red boxes woh jagah hain jahan machine splitting rok deti hai — yeh base cases hain.
★ star se marked boxes (fib3) do baar aate hain, aur ● dot se marked boxes (fib2) teen baar aate hain. Woh repetition — shape aur colour dono se flag ki gayi taaki greyscale mein bhi padhne mein aaye — woh dushman hai jise maarne ke liye poora topic banaya gaya hai.
Intuition Recursion yahan kyun matter karti hai
Memoization kuch nahin hai siwaaye recursion ke jisme ek memory lagi hoti hai. Agar tumhe kisi function ka khud ko call karna comfortable nahin lagta, toh is ke baad jo bhi hai woh sab andhera hai. (Tum kabhi bhi Recursion mein gehraai mein ja sakte ho, lekin yeh page sab kuch define karti hai jo tumhe chahiye.)
Ek base case woh sabse chhota input hai jiska answer hum seedha jaante hain , bina aur recursion ke. Yeh woh floor hai jis par recursion khadi hoti hai.
Tasveer: upar ke tree mein double border waale red boxes — arrows andar jaate hain, lekin koi arrows neeche se bahar nahin jaate, kyunki machine instant jawaab deti hai.
Intuition Humein iska zarurat kyun hai
Base case ke bina machine hamesha split hoti rehti ("fib(2) ka jawaab dene ke liye mujhe fib(1) aur fib(0) ka jawaab chahiye... aur unka jawaab dene ke liye...") aur crash ho jaati. Base case STOP sign hai. Iska value sahi laana poore topic ka sabse zyada error-prone hissa hai — ek galat base value ek perfect recurrence ko perfect bakwaas produce karaati hai.
Definition Recurrence relation
Ek recurrence ek aisa rule hai jo ek value ko ussi cheez ki pehle ki values ke terms mein define karta hai, saath mein ek base case jo use seed karta hai.
Star example Fibonacci hai:
Ab us line mein har symbol decode karo:
F , n , aur F ( n )
F — function ka naam (jaise fib). Bas "Fibonacci machine" ke liye ek label.
n — ek variable , "jis bhi number ke baare mein hum pooch rahe hain" ka placeholder. Jab hum n likhte hain, matlab hum "sequence mein koi position, koi bhi whole number ho sakta hai."
F ( n ) — "machine F input n par chalaayi," yaani n -vaan answer.
n − 1 aur n − 2 — chhote inputs . Kyunki n − 1 < n hai, har step base case ki taraf aage badhta hai. Woh guaranteed shrinking hi wajah hai ki recursion khatam hoti hai.
Intuition Recurrence poora game kyun hai
Memoization ek recurrence ka code mein ek faithful transcription hai. Recurrence nahin ⇒ memoize karne ke liye kuch nahin.
Memory kyon lagaao? Kyunki plain recursion bahut zyada barbaad karti hai jab subproblems repeat hote hain.
Yeh figure call tree mein boxes count karta hai jaise n badhta hai.
2 n , ϕ n , aur O ( ⋅ )
2 n ka matlab hai "2 ko n baar apne aap se multiply karo" (2 3 = 2 × 2 × 2 = 8 ). Yeh explode karta hai: 2 40 ek trillion se zyada hai.
O ( something ) — padhte hain "big-O of " — shorthand hai "kaam kabhi bhi input bade hone par roughly aise badhta hai." O ( n ) = "seedhi line mein badhta hai"; O ( 2 n ) = "dhaamakedaar tarike se badhta hai."
ϕ (Greek "phi") ≈ 1.618 golden ratio hai. Yeh isliye aata hai kyunki tree actually kaise branch karta hai — neeche ka box dekho.
Common mistake "Har level par double hota hai" bilkul sahi nahin hai
Yeh sochne ka mann karta hai ki Fibonacci call tree har level par double hota hai, jo 2 n deta hai. Lekin Figure 1 mein tree dekho: fib(n) split hota hai fib(n-1) aur fib(n-2) mein — aur fib(n-2) branch chhota hai, isliye woh fib(n-1) branch se kam descendants produce karta hai. Tree lopsided hai, perfectly binary nahin.
Calls ko exactly count karne par, nodes ki sankhya ϕ n ki tarah badhti hai jahan ϕ ≈ 1.618 — likha jaata hai Θ ( ϕ n ) (padhte hain "theta of phi-to-the-n", matlab yeh exactly us rate par badhta hai, sirf at most nahin). Toh 2 n ek loose upper bound hai; ϕ n actual rate hai. Kisi bhi tarah yeh exponential hai — jo baat matter karti hai woh yeh hai: kaam multiply hota hai jaise n badhta hai, aur woh catastrophic hai.
Intuition Ek line mein fix
fib(3) ka answer hamesha wahi number hoga. Ise do baar compute karna poori tarah waste hai. Pehli baar likh lo; baad ki har request ek free lookup ban jaati hai. Yahi is poore topic ki justification hai.
Woh "notebook" jisme recursion likhti hai woh ek dictionary hai.
Definition Dictionary (hash map)
Ek dictionary key → value pairs store karti hai aur kisi key ki value almost instantly fetch kar sakti hai. Ek real dictionary socho: ek shabd (key) dhundho, uska matlab (value) pao. Yahan hum ek subproblem (jaise 3) dhundhte hain aur uska answer (jaise 2) paate hain.
Tasveer: ek do-column table. Left column = keys, right column = stored answers. (Aur zyada Hash Maps / Dictionaries mein.)
Jab hum ek dictionary ko specifically already-computed answers store karne ke liye use karte hain, hum ise cache ya memo (short for memoization ) kehte hain. Math mein yeh memo [ state ] likha jaata hai — "is key ke under memo mein stored value."
state
Ek state poori description hai ki tum abhi kaunsa subproblem solve kar rahe ho . Fibonacci ke liye state ek akela number n hai. Ek grid ke liye yeh ek pair (r, c) hai. State bilkul wahi ban jaati hai jo cache mein key banti hai.
Common mistake State complete honi chahiye
Agar answer do chezon par depend karta hai lekin tum cache ko sirf ek se key karte ho, toh do alag subproblems ek hi shelf par land karte hain aur tum galat stored answer fetch karte ho. Socho do alag sawaalon ko ek hi sticky note de rahe ho. Cache key mein har woh variable hona chahiye jo answer ko change karta hai .
Ab tumhare paas har piece hai. Yeh hai poora method , plain step-by-step pseudocode ke roop mein — woh "how" jiske liye yeh page exist karti hai. Yeh pattern hai C-B-R-S: Check, Base, Recurse, Store.
Ise Fibonacci par trace karo taaki abstract steps concrete ban jayein:
fib(5) ek memo ke saath, step by step
fib(5) → memo mein nahin, base nahin → fib(4) aur fib(3) chahiye.
fib(4) → fib(3), fib(2) chahiye; yeh fib(1)=1, fib(0)=0 (base cases) par bottom out karte hain.
Jaise har answer milta hai woh Stored hota hai: memo {2:1, 3:2, 4:3, 5:5} se bhar jaata hai.
Jab fib(5) ki doosri branch dobara fib(3) maangti hai, Check step ise memo mein already paata hai aur 2 instantly return karta hai — koi re-splitting nahin . Woh ek akela lookup hi hai jo Section 3 ke blow-up ko khatam karta hai.
Mnemonic C-B-R-S — "Can Birds Really Sing?"
C heck cache → B ase case → R ecurse → S tore. Classic bug S bhoolna hai: hamesha return karne se pehle store karo.
Ek memo speed khareedti hai, lekin woh free nahin hai — woh time bachaaने ke liye memory kharach karti hai. Dono costs ko honestly naam do.
O ( 1 ) — constant time
O ( 1 ) ka matlab hai "input kitna bhi bada ho, same chhoti si time lagti hai. " Ek dictionary lookup O ( 1 ) hai: key 999 ka answer dhoondna key 3 se zyada slow nahin hai.
Tasveer: ek flat horizontal line — cost kabhi nahin badhti jaise inputs badhte hain.
Intuition Time kyun collapse hoti hai
Ek baar fib(3) memo mein hai, ise dobara maangne par O ( 1 ) lagta hai ek poora subtree dobara ugaane ki jagah. Distinct states count karo, calls nahin: sirf n + 1 distinct inputs hain (0 , 1 , … , n ), har ek ek baar compute hota hai. Toh exponential tree O ( n ) time mein simat jaata hai — ek seedhi line.
Common mistake Speed free nahin hai — memo memory khaata hai
Cache ko physically har distinct state ke liye ek entry store karni hoti hai. Fibonacci ke liye woh n + 1 numbers hain, isliye memory cost O ( n ) hai — space complexity . Upar se, recursion ke ruke hue calls stack up hote hain, aur O ( recursion depth ) aur add hota hai.
Toh honest trade yeh hai: memoization O ( # states ) extra memory kharach karti hai time ko exponential se linear tak cut karne ke liye. Bahut bade state spaces ke liye woh memory bill khud bottleneck ban sakta hai — kabhi mat maano ki caching cost-free hai.
Memoized code memo ko calls ke beech paas karta hai, isliye tumhe ek aakhri vocabulary pair chahiye.
Definition Argument (parameter)
Ek argument woh value hai jo tum function ko call karte waqt dete ho — fib(5) mein 5. Function ke andar, n woh naam hai jo tum jo pass karo usse hold karta hai.
Definition Default argument
memo=None jaisa ek default argument matlab hai "agar caller yeh supply nahin karta, toh yeh fallback use karo." Ek common safe pattern hai memo=None, phir pehli line par if memo is None: memo = {} — yeh har top-level call par ek fresh empty dictionary banata hai.
Common mistake Mutable-default trap (preview)
def solve(n, memo={}) likhna woh {} ek baar create karta hai, jo hamesha ke liye saari calls mein share hota hai, isliye stale answers unrelated runs ke beech leak ho sakte hain. Isliye upar wala safe pattern memo=None use karta hai. Python ka built-in lru_cache decorator cache ko khud manage karke isse poori tarah avoid karta hai.
Ise upar se neeche padhein — yeh upar ke sections ka exact order hai, jo dikhata hai kya kya depend karta hai:
Function (Sec. 0) raw machine hai.
Recursion (Sec. 0) ek function hai jo khud ko call karta hai; ise rukne ke liye ek base case (Sec. 1) chahiye.
Recursion jo pehle ki values ko reference karti hai woh hi ek recurrence (Sec. 2) hai.
Ek recurrence jisme repeated subproblems hain woh exponential blow-up (Sec. 3) paida karta hai — woh dard hai.
Ek dictionary (Sec. 4) jise state (Sec. 4) se key kiya gaya ho free O ( 1 ) lookup (Sec. 6) deti hai.
Inhe C-B-R-S algorithm (Sec. 5) ke saath milao, memory cost (Sec. 6) aur default-argument safety (Sec. 7) ka dhyaan rakho — aur tumhare paas memoization hai.
Function: input to output
Recursion: function calls itself
Base case: where splitting stops
Recurrence: value from smaller values
Blow-up: repeated subproblems
State: full subproblem id
Default argument memo none
Har arrow ka matlab hai "lower box mein upper box ki idea use hoti hai." Koi bhi path MEMOIZATION tak trace karo aur tum dobara trace kar rahe ho kyun har foundation pehle aani thi.
Daayein side cover karo aur check karo ki aage badhne se pehle har sawaal ka jawaab de sakte ho.
Kisi function ke recursive hone ka kya matlab hai? Woh khud ko ek chhote input par call karta hai, base case ki taraf shrink karta hua.
Base case kya hai aur woh kyun zaroori hai?Sabse chhota input jiska answer seedha pata ho; yeh STOP sign hai jo recursion khatam karta hai.
F ( n ) = F ( n − 1 ) + F ( n − 2 ) mein F ( n ) ka kya matlab hai?Fibonacci machine ka input n ke liye output — sequence mein n -vaan number.
Plain recursive Fibonacci exponential kyun hai, aur iska exact growth rate kya hai? Lopsided call tree repeated subproblems ko recompute karta hai; actual node count Θ ( ϕ n ) ki tarah badhta hai jahan ϕ ≈ 1.618 (2 n se upar bounded).
O ( 1 ) ka kya matlab hai?Constant time — input size se regardless same chhoti si cost, jaise ek dictionary lookup.
Dictionary / hash map kya hota hai?Key→value pairs ka store jisme key se near-instant lookup hoti hai.
Memoization mein state kya hai? Current subproblem ki poori description — yeh cache key banta hai.
Memoized algorithm ke chaar steps kya hain? C-B-R-S: Check cache → Base case → Recurse → Store (return se pehle store karo).
Memoization kaun se DO resources kharach karti hai, aur kitni? Time O ( # states ) tak girta hai, lekin memory cache ke liye O ( # states ) aur stack ke liye O ( depth ) tak badhti hai.
def f(n, memo={}) dangerous kyun hai?{} ek baar create hota hai aur saari calls mein share hota hai, jo invocations ke beech stale cached answers leak karta hai.
Memoization ki ek-sentence definition? Ek aisi recursion jo har distinct subproblem ka answer ek cache mein store karti hai taaki woh exactly ek baar compute ho.
Recursion — yahan sab kuch jis engine ke upar hai
Dynamic Programming — woh umbrella jiske neeche yeh ideas rehti hain
Time Complexity Analysis — jahan se Θ ( ϕ n ) aur O ( n ) aate hain
Hash Maps / Dictionaries — cache ki data structure
Divide and Conquer — recursion bina overlap ke (memo ki zarurat nahin)
Tabulation (Bottom-up DP) — woh iterative twin jisse tum aage miloge
lru_cache decorator — Python ka built-in auto-cache