Recursion & Induction Refresher
রিকার্শন ও ইনডাকশন
1. Recursion = Induction in Code
Mathematical induction has two parts: a base case (true for n = 0 or n = 1) and an inductive step (if true for n−1, then true for n). A recursive function has the same two parts: a base case that returns directly, and a recursive case that calls itself on a smaller input. The act of writing a correct recursion is the act of writing an induction proof.
(2) Assume I can solve the problem for n − 1. How do I extend that to n? — that is the recursive step.
যেকোনো রিকার্শনের জন্য — base case + recursive step লিখতে পারলেই কাজ শেষ।
2. Factorial — The Hello World of Recursion
n! = n × (n−1)! with 0! = 1. Translates to four lines of C++:
#include <bits/stdc++.h>
using namespace std;
long long fact(int n) {
if (n <= 1) return 1; // base case
return n * fact(n - 1); // recursive step
}
int main() {
for (int i = 0; i <= 10; i++)
cout << i << "! = " << fact(i) << "\n";
}
n! = n × (n−1)! এবং 0! = 1 — এই দুটি লাইনই যথেষ্ট।
3. The Call Stack — Where Recursion Lives
Each recursive call gets its own stack frame on the program's call stack: return address, parameters, local variables. When the call returns, the frame is popped. Too deep a recursion → stack overflow.
4. Fibonacci, Hanoi & String Reverse
Three classic recursive patterns. Run them — pay attention to the call counts.
#include <bits/stdc++.h>
using namespace std;
long long fib(int n) {
if (n < 2) return n;
return fib(n-1) + fib(n-2);
}
void hanoi(int n, char from, char to, char via) {
if (n == 0) return;
hanoi(n-1, from, via, to);
cout << "Move disk " << n << " from " << from << " to " << to << "\n";
hanoi(n-1, via, to, from);
}
void rev(string& s, int i, int j) {
if (i >= j) return;
swap(s[i], s[j]);
rev(s, i+1, j-1);
}
int main() {
cout << "fib(10) = " << fib(10) << "\n";
hanoi(3, 'A', 'C', 'B');
string s = "hello";
rev(s, 0, s.size()-1);
cout << "reversed: " << s << "\n";
}
5. Tail Recursion & the Bridge to DP
A recursive call is tail-recursive if it is the very last operation in the function — no work happens after it returns. Some compilers turn tail recursion into a loop (no extra stack frames). Naive Fibonacci is not tail-recursive, and it recomputes the same values many times — which is exactly why we need memoisation and dynamic programming (Modules 34–36).
✅ Recursion is great when
- The problem has a clean recursive definition (trees, divide-and-conquer)
- Depth is bounded (≤ ~10⁵)
- You want clean, readable code
⚠️ Avoid recursion when
- Depth could exceed stack size → use iteration / explicit stack
- Same subproblems repeat → use memoisation
- Hot inner loops → rewrite as a loop
6. Practice Problems
Each problem includes a runnable C++ answer. Try yourself first.
-
Write a recursive function that returns the sum of digits of a non-negative integer.একটি অ-ঋণাত্মক পূর্ণসংখ্যার অঙ্কগুলোর যোগফল রিকার্শন দিয়ে বের করুন।
✨ Show Answer (উত্তর দেখুন)
a1.cpp#include <bits/stdc++.h> using namespace std; int ds(int n) { return n == 0 ? 0 : n%10 + ds(n/10); } int main() { cout << ds(12345); } -
Recursively check whether a string is a palindrome (case-sensitive).একটি স্ট্রিং palindrome কিনা — রিকার্শন দিয়ে যাচাই করুন।
✨ Show Answer (উত্তর দেখুন)
a2.cpp#include <bits/stdc++.h> using namespace std; bool pal(const string& s, int i, int j) { if (i >= j) return true; return s[i] == s[j] && pal(s, i+1, j-1); } int main() { string s = "madam"; cout << (pal(s, 0, s.size()-1) ? "yes" : "no"); } -
Print all subsets of
{1, 2, 3}using recursion.{1,2,3}-এর সব subset রিকার্শন দিয়ে প্রিন্ট করুন।✨ Show Answer (উত্তর দেখুন)
a3.cpp#include <bits/stdc++.h> using namespace std; vector<int> cur; void go(vector<int>& a, int i) { if (i == (int)a.size()) { cout << "{ "; for (int x : cur) cout << x << " "; cout << "}\n"; return; } go(a, i+1); cur.push_back(a[i]); go(a, i+1); cur.pop_back(); } int main() { vector<int> a = {1,2,3}; go(a, 0); } -
Recursive Euclidean GCD:
gcd(a, b) = gcd(b, a % b)with basegcd(a, 0) = a.Euclidean GCD অ্যালগরিদমটি রিকার্শন দিয়ে লিখুন।✨ Show Answer (উত্তর দেখুন)
a4.cpp#include <bits/stdc++.h> using namespace std; long long gcd(long long a, long long b) { return b == 0 ? a : gcd(b, a % b); } int main() { cout << gcd(462, 1071); } -
Print the binary representation of a positive integer using recursion (no
bitset).একটি ধনাত্মক পূর্ণসংখ্যার binary রূপ রিকার্শন দিয়ে প্রিন্ট করুন।✨ Show Answer (উত্তর দেখুন)
a5.cpp#include <bits/stdc++.h> using namespace std; void bin(int n) { if (n == 0) return; bin(n / 2); cout << (n % 2); } int main() { bin(42); } -
Recursively compute
x^nin O(log n) using fast power.x^nO(log n) ফাস্ট পাওয়ার রিকার্শন দিয়ে লিখুন।✨ Show Answer (উত্তর দেখুন)
a6.cpp#include <bits/stdc++.h> using namespace std; long long pw(long long x, long long n) { if (n == 0) return 1; long long h = pw(x, n / 2); return (n & 1) ? h * h * x : h * h; } int main() { cout << pw(2, 10); } -
Count the number of ways to climb
nstairs taking 1 or 2 steps at a time (recursive, no DP).nধাপের সিঁড়ি ১ বা ২ ধাপ করে কতভাবে ওঠা যায় — রিকার্শন দিয়ে।✨ Show Answer (উত্তর দেখুন)
a7.cpp#include <bits/stdc++.h> using namespace std; long long ways(int n) { if (n <= 1) return 1; return ways(n-1) + ways(n-2); } int main() { cout << ways(10); } -
Without using a loop, recursively print numbers from 1 to
n, then fromnto 1.কোনো loop ছাড়া রিকার্শন দিয়ে 1 থেকে n এবং তারপর n থেকে 1 প্রিন্ট করুন।✨ Show Answer (উত্তর দেখুন)
a8.cpp#include <bits/stdc++.h> using namespace std; void go(int i, int n) { if (i > n) return; cout << i << " "; // down → up go(i+1, n); cout << i << " "; // up → down on the way back } int main() { go(1, 5); }
Summary — Module 04
Recursion is mathematical induction translated into code: a base case + a step that assumes the smaller case is solved. The call stack stores one frame per active call. Naive recursion can repeat work — that observation will become memoisation and then dynamic programming.