17. Recursion Problems
রিকার্সন শেখার সবচেয়ে ভালো উপায় হলো বিভিন্ন প্রবলেম সলভ করা। এখানে কিছু জনপ্রিয় রিকার্সন প্রবলেম, তাদের Step-by-Step Logic এবং Complexity Analysis আলোচনা করা হলো।
1. ফ্যাক্টোরিয়াল (Factorial)
একটি সংখ্যা n-এর ফ্যাক্টোরিয়াল হলো 1 থেকে n পর্যন্ত সব সংখ্যার গুণফল।
🛠 কর্মপদ্ধতি (Step-by-Step Logic)
- Base Case: যদি
n == 0বাn == 1হয়, তবে 1 রিটার্ন করুন। - Recursive Case: বর্তমান সংখ্যা
n-এর সাথেfactorial(n - 1)গুণ করুন।
📊 কমপ্লেক্সিটি অ্যানালাইসিস (Complexity Analysis)
- Time Complexity: O(n) - n বার ফাংশন কল হয়।
- Space Complexity: O(n) - কল স্ট্যাকের জন্য।
Implementation
java
// Java
public int factorial(int n) {
if (n <= 1) return 1;
return n * factorial(n - 1);
}python
# Python
def factorial(n):
if n <= 1: return 1
return n * factorial(n - 1)2. ফিবোনাচ্চি সিরিজ (Fibonacci Series)
সিরিজটি এমন: 0, 1, 1, 2, 3, 5, 8, 13... যেখানে প্রতিটি সংখ্যা তার আগের দুটি সংখ্যার যোগফল।
🛠 কর্মপদ্ধতি (Step-by-Step Logic)
- Base Case: যদি
n == 0হয়, 0 রিটার্ন করুন। যদিn == 1হয়, 1 রিটার্ন করুন। - Recursive Case:
fib(n - 1) + fib(n - 2)রিটার্ন করুন।
📊 কমপ্লেক্সিটি অ্যানালাইসিস (Complexity Analysis)
- Time Complexity: O(2^n) - এটি এক্সপোনেনশিয়াল (Exponential), কারণ প্রতিটি কলে দুটি করে নতুন কল হয়।
- Space Complexity: O(n) - স্ট্যাকের গভীরতা n পর্যন্ত যায়।
Implementation
java
// Java
public int fib(int n) {
if (n <= 1) return n;
return fib(n - 1) + fib(n - 2);
}python
# Python
def fib(n):
if n <= 1: return n
return fib(n - 1) + fib(n - 2)3. সংখ্যার অংকের যোগফল (Sum of Digits)
যেমন: 123 এর ডিজিটগুলোর যোগফল 1+2+3 = 6।
🛠 কর্মপদ্ধতি (Step-by-Step Logic)
- Base Case: যদি সংখ্যাটি 0 হয়, তবে 0 রিটার্ন করুন।
- Recursive Case: শেষ ডিজিট (
n % 10) নিন এবং বাকি সংখ্যার (n / 10) সাথে যোগ করুন।
Implementation
java
// Java
public int sumOfDigits(int n) {
if (n == 0) return 0;
return (n % 10) + sumOfDigits(n / 10);
}python
# Python
def sum_of_digits(n):
if n == 0: return 0
return (n % 10) + sum_of_digits(n // 10)4. পাওয়ার ক্যালকুলেশন (Power Calculation - x^n)
🛠 কর্মপদ্ধতি (Step-by-Step Logic)
- Base Case: যদি
n == 0হয়, তবে 1 রিটার্ন করুন। - Recursive Case:
x * power(x, n - 1)রিটার্ন করুন। - Optimization: দ্রুত করার জন্য
divide and conquer(O(log n)) ব্যবহার করা যায়।
Implementation
java
// Java
public int power(int x, int n) {
if (n == 0) return 1;
return x * power(x, n - 1);
}python
# Python
def power(x, n):
if n == 0: return 1
return x * power(x, n - 1)5. টাওয়ার অফ হ্যানয় (Tower of Hanoi)
এটি একটি ক্লাসিক্যাল রিকার্সন প্রবলেম যেখানে তিনটি পোল এবং কিছু ডিস্ক থাকে। বড় ডিস্কের ওপর ছোট ডিস্ক সবসময় রাখতে হবে।
🛠 কর্মপদ্ধতি (Step-by-Step Logic)
n-1সংখ্যক ডিস্ককে সোর্স পোল থেকে অক্সিলিয়ারি পোলে সরিয়ে নিন।- সবচেয়ে বড় ডিস্কটিকে সোর্স থেকে ডেস্টিনেশন পোলে নিন।
- এবার
n-1সংখ্যক ডিস্ককে অক্সিলিয়ারি থেকে ডেস্টিনেশন পোলে নিয়ে আসুন।
📊 কমপ্লেক্সিটি অ্যানালাইসিস (Complexity Analysis)
- Time Complexity: O(2^n - 1) - n সংখ্যক ডিস্কের জন্য মুভমেন্ট সংখ্যা।
Implementation
java
// Java
public void towerOfHanoi(int n, char from, char to, char aux) {
if (n == 1) {
System.out.println("Move disk 1 from " + from + " to " + to);
return;
}
towerOfHanoi(n - 1, from, aux, to);
System.out.println("Move disk " + n + " from " + from + " to " + to);
towerOfHanoi(n - 1, aux, to, from);
}python
# Python
def tower_of_hanoi(n, source, destination, auxiliary):
if n == 1:
print(f"Move disk 1 from {source} to {destination}")
return
tower_of_hanoi(n - 1, source, auxiliary, destination)
print(f"Move disk {n} from {source} to {destination}")
tower_of_hanoi(n - 1, auxiliary, destination, source)6. 1 থেকে N প্রিন্ট করা (Print 1 to N)
🛠 কর্মপদ্ধতি (Step-by-Step Logic)
- Base Case: যদি
n == 0হয়, তবে থামুন। - Recursive Case (Head Recursion): প্রথমে
print(n-1)কল করুন, তারপরnপ্রিন্ট করুন। এটি করলে 1 থেকে N ক্রমে প্রিন্ট হবে।
Implementation
java
// Java
public void print1ToN(int n) {
if (n == 0) return;
print1ToN(n - 1);
System.out.print(n + " ");
}python
# Python
def print_1_to_n(n):
if n == 0: return
print_1_to_n(n - 1)
print(n, end=" ")7. অ্যারের যোগফল (Sum of Array)
🛠 কর্মপদ্ধতি (Step-by-Step Logic)
- Base Case: ইনডেক্স যদি শেষ হয়ে যায়, 0 রিটার্ন করুন।
- Recursive Case: বর্তমান ইনডেক্সের ভ্যালুর সাথে পরের অংশের যোগফল যোগ করুন।
Implementation
java
// Java
public int arraySum(int[] arr, int n) {
if (n <= 0) return 0;
return arraySum(arr, n - 1) + arr[n - 1];
}python
# Python
def array_sum(arr, n):
if n <= 0: return 0
return array_sum(arr, n - 1) + arr[n - 1]8. স্ট্রিং রিভার্স (Reverse String)
🛠 কর্মপদ্ধতি (Step-by-Step Logic)
- Base Case: স্ট্রিং যদি খালি হয়, খালি স্ট্রিং রিটার্ন করুন।
- Recursive Case: শেষ ক্যারেক্টারটি নিয়ে তার আগে বাকিগুলোর রিভার্স অংশ যোগ করুন।
Implementation
java
// Java
public String reverseString(String s) {
if (s.isEmpty()) return s;
return reverseString(s.substring(1)) + s.charAt(0);
}python
# Python
def reverse_string(s):
if len(s) == 0: return s
return reverse_string(s[1:]) + s[0]IMPORTANT
রিকার্সন প্রবলেম সলভ করার সময় সব সময় মনে রাখবেন: প্রথমে Base Case চিন্তা করুন, তারপর বড় সমস্যাটিকে কীভাবে একটি ধাপে ছোট করা যায় তা ভাবুন।
TIP
ফিবোনাচ্চির মতো এক্সপোনেনশিয়াল প্রবলেমগুলোকে ফাস্ট করার জন্য আমরা পরে Dynamic Programming (DP) শিখব।