Recursive function base case చేరుకునే వరకు సమస్య యొక్క చిన్న రూపంతో తనను తాను call చేసుకుంటుంది.
ప్రతి recursion కి రెండు విషయాలు కావాలి:
def factorial(n):
if n <= 1: # base case
return 1
return n * factorial(n - 1) # recursive case
ప్రతి recursive call call stack పైకి frame push చేస్తుంది. Base case return అయినప్పుడు, frames రివర్స్ క్రమంలో pop అవుతాయి.
factorial(4)
→ factorial(3)
→ factorial(2)
→ factorial(1) → 1 return చేస్తుంది
← 2 return చేస్తుంది
← 6 return చేస్తుంది
← 24 return చేస్తుంది
Base case లేకపోతే, stack overflow అవుతుంది. Python default recursion limit 1,000 frames.
Naïve recursive Fibonacci O(2ⁿ) ఎందుకంటే ఇది అదే sub-problems ను మళ్ళీ మళ్ళీ compute చేస్తుంది. Memoisation దీన్ని O(n) time మరియు space లో పరిష్కరిస్తుంది.
from functools import lru_cache
@lru_cache(maxsize=None)
def fib(n):
if n < 2:
return n
return fib(n - 1) + fib(n - 2)
Backtracking అనేది twist తో recursion: మీరు ఎంపిక చేసి, recurse చేసి, తదుపరి option ప్రయత్నించే ముందు ఎంపికను రద్దు చేస్తారు. Maze explore చేయడం అనుకోండి - ముందుకు నడవండి, dead end తగిలితే వెనక్కి, తదుపరి path ప్రయత్నించండి.
def backtrack(state, choices):
if is_solution(state):
result.append(state.copy())
return
for choice in choices:
if is_valid(choice):
state.add(choice) # ఎంచుకో
backtrack(state, ...) # explore చేయి
state.remove(choice) # రద్దు చేయి
ఈ మూడు-దశల pattern - ఎంచుకో, explore చేయి, రద్దు చేయి - దాదాపు ప్రతి backtracking సమస్య యొక్క వెన్నెముక.
Sign in to join the discussion
Backtracking template లో, recursive call తర్వాత ఎంపికను ఎందుకు రద్దు చేస్తాం?
[1, 2, 3] యొక్క అన్ని వరుసక్రమాలు generate చేయండి. ప్రతి level లో, ఉపయోగించని number ఎంచుకోండి, recurse చేయండి, తర్వాత un-pick చేయండి.
[]
/ | \
[1] [2] [3]
/ \ ...
[1,2] [1,3]
| |
[1,2,3] [1,3,2] ... (6 మొత్తం)
n! permutations ఉంటాయి, కాబట్టి time complexity O(n × n!).
Combinations (n choose k): ప్రతి element వద్ద, దాన్ని చేర్చండి లేదా skip చేయండి, duplicates నివారించడానికి ముందుకు మాత్రమే recurse చేయండి.
Subsets: size constraint లేకుండా అదే ఆలోచన - recursion tree లో ప్రతి node valid subset. 2ⁿ subsets ఉంటాయి.
N×N board పై N queens ను ఒకరినొకరు attack చేయకుండా ఉంచండి. N=4 కి:
. Q . .
. . . Q
Q . . .
. . Q .
వ్యూహం: ప్రతి row కి ఒక queen ఉంచండి. ప్రతి row కి ప్రతి column ప్రయత్నించండి. Column, main diagonal మరియు anti-diagonal conflicts తనిఖీ చేయండి. Safe అయితే ఉంచి తదుపరి row కి recurse చేయండి. Stuck అయితే backtrack.
మూడు sets తో conflicts track చేయండి: cols, diag (row − col) మరియు anti_diag (row + col).
N-Queens సమస్యలో diagonal conflicts ను సమర్థవంతంగా ఎలా తనిఖీ చేస్తాం?
ఖాళీ cell కనుగొని, 1–9 digits ప్రయత్నించండి. ప్రతి digit కి row, column మరియు 3×3 box constraints తనిఖీ చేయండి. Valid అయితే ఉంచి recurse చేయండి. ఏ digit పనిచేయకపోతే, undo చేసి backtrack. Constraints నుండి pruning భారీ search space ఉన్నప్పటికీ దీన్ని సాధ్యం చేస్తుంది.
2D letters board మరియు target word ఇచ్చినప్పుడు, ప్రతి cell నుండి ప్రారంభించి నాలుగు దిశలలో DFS చేయండి, ఒక character చొప్పున match చేస్తూ. Recursion సమయంలో cells ను visited గా mark చేసి, backtrack చేసేటప్పుడు unmark చేయండి.
ఖర్చు branching factor (ప్రతి step లో choices) మరియు depth (solution కి steps) పై ఆధారపడుతుంది. b branches మరియు d depth కి: O(bᵈ).
| సమస్య | Branching | Depth | Complexity | |--------|-----------|-------|------------| | Permutations | n, n−1, … | n | O(n!) | | Subsets | 2 | n | O(2ⁿ) | | N-Queens | ~n | n | O(n!) worst case |
Pruning అంటే విఫలమవుతాయని తెలిసిన branches ను skip చేయడం. ఉదాహరణలు:
మంచి pruning అసాధ్యమైన search ను వేగవంతమైనదిగా మార్చగలదు.
Backtracking algorithm లో pruning ఏమి చేస్తుంది?