A structured guide to master Recursion & Backtracking from basics β advanced with logic, dry runs, and patterns.
Recursion is a technique where a function calls itself to solve smaller subproblems.
- Base Case β stopping condition
- Recursive Call β function calls itself
- Work β processing before/after call
n! = n * (n-1)!
int fact(int n){
if(n==0) return 1;
return n * fact(n-1);
}fact(3)
= 3 * fact(2)
= 3 * 2 * fact(1)
= 3 * 2 * 1 * fact(0)
= 6
f(n) = f(n-1) + f(n-2)
int fib(int n){
if(n<=1) return n;
return fib(n-1) + fib(n-2);
}int sum(int n){
if(n==0) return 0;
return n + sum(n-1);
}void sum(int n, int s){
if(n==0){
cout<<s;
return;
}
sum(n-1, s+n);
}int power(int a,int b){
if(b==0) return 1;
return a * power(a,b-1);
}void print(int n){
if(n==0) return;
print(n-1);
cout<<n<<" ";
}void print(int n){
if(n==0) return;
cout<<n<<" ";
print(n-1);
}π MOST IMPORTANT for CP
void solve(int i, vector<int>& arr, vector<int>& ds){
if(i==arr.size()){
for(auto x:ds) cout<<x<<" ";
cout<<endl;
return;
}
// pick
ds.push_back(arr[i]);
solve(i+1, arr, ds);
// not pick
ds.pop_back();
solve(i+1, arr, ds);
}[]
[1]
[2]
[1,2]
void solve(int i, vector<int>& arr, int sum, int k){
if(i==arr.size()){
if(sum==k) cout<<"YES\n";
return;
}
solve(i+1, arr, sum+arr[i], k);
solve(i+1, arr, sum, k);
}vector<vector<int>> subsets(vector<int>& nums){
vector<vector<int>> res;
int n=nums.size();
for(int mask=0;mask<(1<<n);mask++){
vector<int> temp;
for(int i=0;i<n;i++){
if(mask & (1<<i))
temp.push_back(nums[i]);
}
res.push_back(temp);
}
return res;
}void permute(vector<int>& nums, int idx){
if(idx==nums.size()){
for(int x:nums) cout<<x<<" ";
cout<<endl;
return;
}
for(int i=idx;i<nums.size();i++){
swap(nums[i],nums[idx]);
permute(nums,idx+1);
swap(nums[i],nums[idx]);
}
}void solve(int i, vector<int>& arr, int target, vector<int>& ds){
if(target==0){
for(int x:ds) cout<<x<<" ";
cout<<endl;
return;
}
if(i==arr.size()) return;
if(arr[i]<=target){
ds.push_back(arr[i]);
solve(i, arr, target-arr[i], ds);
ds.pop_back();
}
solve(i+1, arr, target, ds);
}void reverse(string &s, int i){
if(i>=s.size()/2) return;
swap(s[i], s[s.size()-i-1]);
reverse(s, i+1);
}bool isPal(string s,int i){
if(i>=s.size()/2) return true;
if(s[i]!=s[s.size()-i-1]) return false;
return isPal(s,i+1);
}bool sorted(vector<int>& arr,int i){
if(i==arr.size()-1) return true;
if(arr[i]>arr[i+1]) return false;
return sorted(arr,i+1);
}bool isSafe(int row,int col,vector<string>& board,int n){
for(int i=0;i<col;i++)
if(board[row][i]=='Q') return false;
for(int i=row,j=col;i>=0 && j>=0;i--,j--)
if(board[i][j]=='Q') return false;
for(int i=row,j=col;i<n && j>=0;i++,j--)
if(board[i][j]=='Q') return false;
return true;
}void solve(int i,int j,vector<vector<int>>& m,int n,string path){
if(i==n-1 && j==n-1){
cout<<path<<endl;
return;
}
}void mergeSort(vector<int>& a,int l,int r){
if(l>=r) return;
int mid=(l+r)/2;
mergeSort(a,l,mid);
mergeSort(a,mid+1,r);
}int dp[100];
int fib(int n){
if(n<=1) return n;
if(dp[n]!=-1) return dp[n];
return dp[n]=fib(n-1)+fib(n-2);
}int height(Node* root){
if(root==NULL) return 0;
return 1 + max(height(root->left), height(root->right));
}- Bitmask recursion
- DFS (graph traversal)
- Meet in the middle
- Pruning
- Basic recursion
- Subsequence
- Permutations
- Backtracking
- Divide & conquer
- Trees
- DP (memoization)
- Factorial
- Fibonacci
- Print 1 to N
- Subsets
- Permutations
- Combination Sum
- N-Queens
- Sudoku Solver
- Rat in a Maze
-
Always identify:
- Base case
- Choice (pick/not pick)
-
Think in tree structure
-
Practice dry runs manually
Recursion = π Breaking problem into smaller parts π Solving via function calls π Combining results
Master this β you unlock:
- Backtracking
- DP
- Graphs
- Trees
π‘ Keep practicing β recursion becomes intuitive only with repetition!