রিকার্সিভ অ্যালগরিদমের জটিলতা
এই পাঠে যা শিখবেন
- একটি রিকার্সিভ অ্যালগরিদমের ধাপ সংখ্যাকে রিকারেন্স হিসেবে লেখা
- নেইভ ফিবোনাচির রিকারেন্স ক্যারেক্টারিস্টিক ইকুয়েশন (L30) দিয়ে সমাধান করে $\Theta(\varphi^n)$ পাওয়া
- merge sort ও binary search-এর রিকারেন্স Master Theorem (L31) দিয়ে সমাধান করা
- Python কোডে নেইভ বনাম মেমোয়াইজড ফিবোনাচির কল সংখ্যা লাইভ ইনস্ট্রুমেন্ট করে তুলনা করা
১ · রিকারেন্স থেকে জটিলতায়
M6-এ (L29-L32) আমরা রিকারেন্স রিলেশন সমাধান করার গণিত শিখেছি — কিন্তু সেখানে এই সমাধানগুলো শুধু গাণিতিক অনুশীলন ছিল। এই পাঠে সেই একই গণিত সরাসরি ব্যবহার হবে: যখন একটি অ্যালগরিদম নিজেকে রিকার্সিভভাবে কল করে, তার "ধাপ সংখ্যা" $T(n)$ প্রায় সবসময় একটি রিকারেন্স রিলেশন মেনে চলে। সেই রিকারেন্স সমাধান করাই অ্যালগরিদমের জটিলতা বের করার পদ্ধতি।
২ · ওয়ার্কড উদাহরণ ১ — নেইভ রিকার্সিভ ফিবোনাচি
L29-এ দেখা ফিবোনাচি সংজ্ঞা $F(n)=F(n-1)+F(n-2)$ সরাসরি কোডে বসালে (memoization ছাড়া), প্রতিটি কল দুটি নতুন রিকার্সিভ কল তৈরি করে। এই ফাংশনের কল সংখ্যা $T(n)$-এর রিকারেন্স: $$T(n) = T(n-1) + T(n-2) + O(1)$$ এটি L31-এর ডিভাইড-অ্যান্ড-কনকার ফর্ম ($T(n)=aT(n/b)+f(n)$) নয় — তাই Master Theorem এখানে প্রযোজ্য নয়। কিন্তু এটি ঠিক L30-এর ধরনের একটি ২য়-ক্রম লিনিয়ার হোমোজিনিয়াস রিকারেন্স। ক্যারেক্টারিস্টিক ইকুয়েশন: $$x^2 = x + 1 \implies x^2 - x - 1 = 0 \implies x = \frac{1 \pm \sqrt5}{2}$$ পজিটিভ মূল $\varphi = \frac{1+\sqrt5}{2} \approx 1.618$ — বিখ্যাত গোল্ডেন রেশিওGolden Ratio (φ)≈১.৬১৮, একটি বিশেষ ধ্রুবক যা ফিবোনাচি সিকোয়েন্সের ক্যারেক্টারিস্টিক ইকুয়েশনের মূল হিসেবে স্বাভাবিকভাবে বেরিয়ে আসে।। এর মানে $T(n) = \Theta(\varphi^n)$ — এক্সপোনেনশিয়াল। তাই নেইভ রিকার্সিভ ফিবোনাচি বড় $n$-এ ব্যবহারিকভাবে অসম্ভব ধীর।
৩ · ওয়ার্কড উদাহরণ ২ ও ৩ — Merge Sort ও Binary Search (L31 পুনর্ব্যবহার)
এবার L31-এর দুটি ফলাফল সরাসরি পুনর্ব্যবহার করি:
- Merge sort: $T(n)=2T(n/2)+\Theta(n)$। এখানে $a=2,b=2$, তাই $\log_b a = \log_2 2 = 1$, এবং $f(n)=n=n^{\log_b a}$ — Master Theorem কেস ২ প্রযোজ্য, তাই $T(n)=\Theta(n\log n)$।
- Binary search: $T(n)=T(n/2)+\Theta(1)$। এখানে $a=1,b=2$, তাই $\log_b a=\log_2 1=0$, এবং $f(n)=\Theta(1)=n^0=n^{\log_b a}$ — আবার কেস ২, তাই $T(n)=\Theta(\log n)$।
M6-এ আমরা বিমূর্তভাবে রিকারেন্স সমাধান করার কৌশল শিখেছিলাম — ক্যারেক্টারিস্টিক ইকুয়েশন, Master Theorem। এই পাঠে দেখা গেল সেই একই কৌশল সরাসরি বলে দেয় কোন অ্যালগরিদম ব্যবহারযোগ্য (merge sort, binary search — polynomial/logarithmic) আর কোনটি নয় (নেইভ ফিবোনাচি — exponential)। এটাই বিচ্ছিন্ন গণিত ও বাস্তব প্রোগ্রামিং সিদ্ধান্তের মধ্যে সবচেয়ে সরাসরি সংযোগগুলোর একটি।
৪ · কোড: নেইভ বনাম মেমোয়াইজড — কল সংখ্যায় ব্যবধান
তত্ত্ব অনুযায়ী নেইভ ফিবোনাচি এক্সপোনেনশিয়াল আর মেমোয়াইজড সংস্করণ (L29-এ ইঙ্গিত করা, DSA কোর্সে dynamic programming হিসেবে বিস্তারিত) লিনিয়ার। নিচের কোডে আমরা সংখ্যাটি অনুমান করছি না — সরাসরি একটি কাউন্টার দিয়ে ইনস্ট্রুমেন্ট করে গণনা করছি:
# নেইভ রিকার্সিভ ফিবোনাচি — প্রতিটি ফাংশন-কলে কাউন্টার বাড়বে
naive_calls = 0
def fib_naive(n):
global naive_calls
naive_calls += 1
if n < 2:
return n
return fib_naive(n - 1) + fib_naive(n - 2)
n = 20
result_naive = fib_naive(n)
print(f"fib_naive({n}) = {result_naive} | মোট ফাংশন-কল: {naive_calls}")
# মেমোয়াইজড ফিবোনাচি — একই n দ্বিতীয়বার গণনা করা হয় না (cache miss-এই শুধু কাউন্ট বাড়বে)
memo = {}
memo_computations = 0
def fib_memo(n):
global memo_computations
if n in memo:
return memo[n]
memo_computations += 1
if n < 2:
memo[n] = n
return n
result = fib_memo(n - 1) + fib_memo(n - 2)
memo[n] = result
return result
result_memo = fib_memo(n)
print(f"fib_memo({n}) = {result_memo} | মোট নতুন গণনা: {memo_computations}")
ratio = naive_calls / memo_computations
print(f"\nনেইভ, মেমোয়াইজডের চেয়ে {ratio:.1f} গুণ বেশি কল করেছে!")
ভাবনার প্রশ্ন
প্রতিটি প্রশ্ন নিজে কিছুক্ষণ ভাবুন — তারপর "→ উত্তর" চাপুন।
প্র ০১ নেইভ ফিবোনাচির রিকারেন্স $T(n)=T(n-1)+T(n-2)+O(1)$-এ কেন Master Theorem প্রযোজ্য নয়?
Master Theorem শুধুমাত্র ডিভাইড-অ্যান্ড-কনকার ফর্ম $T(n)=aT(n/b)+f(n)$-এর রিকারেন্সে কাজ করে — যেখানে সমস্যাটি একটি ভাগফলে (যেমন $n/2$) ছোট হয়। কিন্তু ফিবোনাচির রিকারেন্সে সমস্যাটি একটি বিয়োগফলে ($n-1$, $n-2$) ছোট হয় — সম্পূর্ণ ভিন্ন কাঠামো। এই ধরনের রিকারেন্সের জন্য L30-এর ক্যারেক্টারিস্টিক ইকুয়েশন পদ্ধতিই সঠিক টুল, Master Theorem নয়।
প্র ০২ মেমোয়াইজেশন কেন শুধু "কিছুটা দ্রুততর" নয়, বরং সম্পূর্ণ ভিন্ন জটিলতা ক্লাসে ($\Theta(\varphi^n) \to \Theta(n)$) নিয়ে যায়?
নেইভ সংস্করণে একই সাব-প্রবলেম (যেমন $fib(10)$) বহুবার recompute হয় — মোট ইউনিক সাব-প্রবলেম মাত্র $n+1$টি হলেও, রিকার্সিভ কল ট্রি-তে এদের পুনরাবৃত্তি এক্সপোনেনশিয়াল হারে বাড়ে। মেমোয়াইজেশন প্রতিটি সাব-প্রবলেম ঠিক একবার সমাধান করে, ফলাফল সংরক্ষণ করে — তাই মোট কাজ ইউনিক সাব-প্রবলেমের সংখ্যার সমানুপাতিক, যা এখানে লিনিয়ার। এটি একটি "কনস্ট্যান্ট ফ্যাক্টর" উন্নতি নয় — এটি সম্পূর্ণ ভিন্ন জটিলতা ক্লাসে যাওয়া।
প্র ০৩ L40-এর সাথে সংযোগ করে ভাবুন: quicksort-এর রিকারেন্স কেন merge sort-এর মতো একটি নির্দিষ্ট রিকারেন্স নয়?
Merge sort সবসময় ইনপুটকে ঠিক দুটি সমান অর্ধেকে ভাগ করে — তাই এর রিকারেন্স $T(n)=2T(n/2)+\Theta(n)$ ইনপুট-নিরপেক্ষভাবে স্থির। কিন্তু quicksort-এর ভাগ pivot-এর অবস্থানের উপর নির্ভর করে — worst case-এ pivot সবচেয়ে ছোট/বড় হলে ভাগটি হয় $1$ ও $n-1$ (রিকারেন্স $T(n)=T(n-1)+\Theta(n)$, যা সমাধান করলে $\Theta(n^2)$), আর গড় কেসে ভাগ প্রায় সমান হয় (রিকারেন্স $T(n)=2T(n/2)+\Theta(n)$-এর কাছাকাছি, $\Theta(n\log n)$)। তাই quicksort-এর "একটি" রিকারেন্স নেই — এটি ইনপুটের উপর নির্ভরশীল, যা সরাসরি L40-এর আলোচনার সাথে যুক্ত।
অনুশীলন
-
পরীক্ষা করুন: কোড সেলে
n = 25করে Run চাপুন (সাবধান — এটি একটু সময় নিতে পারে)। নেইভ কল সংখ্যা কতটা বেড়েছে লক্ষ করুন।যেহেতু নেইভ ফিবোনাচি $\Theta(\varphi^n)$, $n$ ৫ বাড়লে কল সংখ্যা প্রায় $\varphi^5 \approx 11.1$ গুণ বেড়ে যাবে (কারণ $T(n+5)/T(n) \approx \varphi^5$)। এই দ্রুত বৃদ্ধিই দেখায় কেন naive recursion ছোট $n$-এর বাইরে ব্যবহারযোগ্য নয়।
-
যাচাই করুন: $T(n)=3T(n/2)+n$ রিকারেন্সের জন্য Master Theorem-এর কোন কেস প্রযোজ্য তা L31-এর পদ্ধতিতে নির্ণয় করুন ($\log_b a$ গণনা করে $f(n)$-এর সাথে তুলনা করুন)।
এখানে $a=3, b=2$, তাই $\log_2 3 \approx 1.585$। $f(n)=n=n^1$, যা $n^{1.585}$-এর চেয়ে ধীরে বাড়ে — অর্থাৎ $f(n)=O(n^{\log_b a - \epsilon})$ কোনো $\epsilon>0$-এর জন্য (এখানে $\epsilon\approx0.585$)। তাই Master Theorem কেস ১ প্রযোজ্য: $T(n)=\Theta(n^{\log_2 3}) \approx \Theta(n^{1.585})$।
আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ
- কোর্সের সম্পূর্ণ সিলেবাস দেখুন ৪৪টি পাঠ পরবর্তী পাঠ — P বনাম NP — কোন সমস্যা আদৌ দক্ষতার সাথে সমাধানযোগ্য তার সীমারেখা আলোচনা করবে।
- পরবর্তী পাঠ L42 P বনাম NP ও NP-সম্পূর্ণতা পরিচিতি — কম্পিউটার সায়েন্সের সবচেয়ে বিখ্যাত অমীমাংসিত প্রশ্ন।
- Data Structures & Algorithms কোর্স সঙ্গী কোর্স Dynamic programming ও memoization-এর সম্পূর্ণ বাস্তবায়ন দেখতে DSA কোর্সটি দেখুন।