Complexity Analysis — Big-O, Θ, Ω
চালু করার আগেই গতি সম্পর্কে যুক্তি
1. Why Reason Mathematically?
O(n²) প্রোগ্রাম n = 100-এ ঠিক চলে, n = 10⁶-এ মরে। সব case benchmark করা সম্ভব না। Big-O দিয়ে — code চালানোর আগেই — scalability সম্পর্কে যুক্তি দেওয়া যায়।
2. Formal Definitions
| Notation | Meaning |
|---|---|
| f(n) = O(g(n)) | upper bound — f g-এর চেয়ে দ্রুত বাড়ে না |
| f(n) = Ω(g(n)) | lower bound — f অন্তত g-এর মতো দ্রুত বাড়ে |
| f(n) = Θ(g(n)) | tight bound — একই growth rate |
| f(n) = o(g(n)) | strictly slower growth |
Formally: f(n) = O(g(n)) iff ∃ c > 0, n₀ ≥ 0 such that ∀ n ≥ n₀: f(n) ≤ c · g(n)।
3. Common Complexity Classes
O(1) constant — array index
O(log n) logarithmic — binary search
O(n) linear — single pass
O(n log n) linearithmic — merge sort
O(n²) quadratic — nested loop
O(n³) cubic — triple loop
O(2ⁿ) exponential — naive Fibonacci
O(n!) factorial — all permutations
4. Empirical Measurement
কোড চালিয়ে আসলেই কত সময় লাগে দেখা যাক — linear vs quadratic-এর পার্থক্য স্পষ্ট।
#include <stdio.h>
#include <time.h>
long linear(int n) {
long s = 0;
for (int i = 0; i < n; i++) s += i;
return s;
}
long quadratic(int n) {
long s = 0;
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++) s += 1;
return s;
}
int main(void) {
int sizes[] = { 1000, 5000, 10000 };
for (int i = 0; i < 3; i++) {
int n = sizes[i];
clock_t t1 = clock(); linear(n); clock_t t2 = clock();
clock_t t3 = clock(); quadratic(n); clock_t t4 = clock();
printf("n=%d linear=%.3fms quadratic=%.3fms\n",
n,
1000.0 * (t2 - t1) / CLOCKS_PER_SEC,
1000.0 * (t4 - t3) / CLOCKS_PER_SEC);
}
return 0;
}
n দ্বিগুণ করলে linear ~2x সময়, quadratic ~4x সময়। Online compiler-এ timing variable — প্যাটার্ন-ই দেখুন।
5. Analyzing Code
for (int i = 0; i < n; i++) // O(n)
for (int j = 0; j < n; j++) // O(n)
for (int k = 1; k < n; k *= 2) // O(log n)
... // total: O(n² log n)
6. Amortized Analysis
Dynamic array append worst case O(n) (যখন realloc দ্বিগুণ হয়), কিন্তু n-বার append-এর মোট কাজ O(n) — per-operation amortized O(1)।
7. Master Theorem
T(n) = aT(n/b) + f(n)
f(n) vs n^log_b(a):
Case 1: f smaller → T = Θ(n^log_b(a))
Case 2: same → T = Θ(n^log_b(a) · log n)
Case 3: f larger → T = Θ(f(n))
Example: Merge sort T(n) = 2T(n/2) + n
log_2(2) = 1, f(n) = n → Case 2 → T(n) = Θ(n log n)
8. Contest Time Budget (1 second)
| n | Fits |
|---|---|
| 10⁸ | O(n) |
| 10⁷ | O(n log n) |
| 10⁴ | O(n²) |
| 500 | O(n³) |
| 25 | O(2ⁿ) |
| 10 | O(n!) |
9. Practice Problems
- Give Big-O of: single loop to n; nested loops;
while (n >= 1) n /= 2;.Complexity বলুন।✨ Show Answer
O(n), O(n²), O(log n)।
- Prove 3n² + 5n + 7 = O(n²) using the formal definition.Formal definition দিয়ে প্রমাণ।
✨ Show Answer
n ≥ 1-এর জন্য 3n² + 5n + 7 ≤ 3n² + 5n² + 7n² = 15n²। অর্থাৎ c = 15, n₀ = 1 নিলেই 3n² + 5n + 7 ≤ 15n² হয় — তাই O(n²)। ∎
- Big-O of merge sort with Master Theorem.Merge sort-এর complexity।
✨ Show Answer
T(n) = 2T(n/2) + Θ(n) → Master Theorem Case 2 → Θ(n log n)।
- Worst/best/average of quicksort.Quicksort-এর সব case।
✨ Show Answer
Worst O(n²) (already-sorted + fixed pivot)। Average & best O(n log n)। Random pivot-এ worst case avoid হয়।
- Space complexity of recursive factorial.Recursive factorial-এর space।
✨ Show Answer
Recursion depth n → stack O(n)। Iterative version O(1)।
- Amortized cost of n pushes into dynamic array.n-বার dynamic-array push-এর amortized cost।
✨ Show Answer
Resize-এর সময় 1 + 2 + 4 + … + n ≈ 2n কাজ — মোট O(n), per-push O(1) amortized।
- Compare bubble vs merge sort for n = 10⁵.n = 10⁵-এ bubble vs merge।
✨ Show Answer
Bubble ~10¹⁰ operations (কয়েক মিনিট)। Merge ~10⁵ × 17 = 1.7×10⁶ (মিলিসেকেন্ড)। প্রায় ১০০০০ গুণ পার্থক্য।
- Given 2 sec budget, what algorithmic class fits n = 10⁶?2 সেকেন্ডে n = 10⁶-এ কোন class?
✨ Show Answer
~2×10⁸ operations budget। O(n log n) (n·20 ≈ 2×10⁷) — আরামদায়ক। O(n²) বাদ।
- Big-O of traversing a binary tree.Tree traversal-এর Big-O।
✨ Show Answer
প্রতিটি node একবার visit — O(n)। Stack space: worst O(n) (skewed), balanced O(log n)।
- Big-O of BFS and DFS.BFS/DFS-এর Big-O।
✨ Show Answer
O(V + E) — প্রতিটি vertex ও edge একবার করে visit।
- Big-O of naive Fibonacci vs memoized.Naive ও memoized Fibonacci।
✨ Show Answer
Naive O(2ⁿ) — subproblems-এ exponential repetition। Memoized O(n) — প্রতিটি subproblem একবার গণনা।
- Is O(n + m) the same as O(n)?O(n+m) ও O(n) কি এক?
✨ Show Answer
যদি m = O(n) হয়, তবে হ্যাঁ। কিন্তু যদি m স্বাধীন ভেরিয়েবল হয় (গ্রাফে V, E যেমন), তাহলে না — দুটি আলাদা parameter।
- Does O(2n) = O(n)? Why?O(2n) = O(n) কেন?
✨ Show Answer
Big-O constant factor উপেক্ষা করে: c = 2 এই definition-এই কাজ করে। Asymptotically একই class।
- Solve T(n) = 2T(n/2) + n using Master Theorem.Master Theorem দিয়ে সমাধান।
✨ Show Answer
log_2(2) = 1, f(n) = n = n¹ — Case 2 → T(n) = Θ(n log n)।
- Measure empirically: time sort on n = 10³, 10⁴, 10⁵; fit the curve.Sort-এর runtime পরিমাপ করুন।
✨ Show Answer
Section 4-এর
bench.cধাঁচের কোড লিখুন —clock_gettime(CLOCK_MONOTONIC, ...)ব্যবহার করলে আরও নির্ভুল timing। Log-log plot-এ slope = complexity exponent।
Glossary (শব্দকোষ)
| Term | Meaning | বাংলায় |
|---|---|---|
| Asymptotic Analysis | Studying behavior as input size grows toward infinity. | Input বিশাল হলে আচরণ কী — তার বিশ্লেষণ। |
| Big-O (O) | Upper bound on growth rate. | বৃদ্ধির ঊর্ধ্বসীমা। |
| Big-Omega (Ω) | Lower bound on growth rate. | বৃদ্ধির নিম্নসীমা। |
| Big-Theta (Θ) | Tight bound — both upper and lower. | উভয় দিক থেকে আঁটসাঁট সীমা। |
| Time Complexity | How runtime scales with input size. | Runtime কীভাবে input-এর সাথে বাড়ে। |
| Space Complexity | How memory use scales with input size. | Memory ব্যবহার কীভাবে বাড়ে। |
| Constant Time — O(1) | Cost does not grow with n. | n-এর সাথে cost বাড়ে না। |
| Logarithmic — O(log n) | Halves the search space each step. | প্রতি ধাপে অর্ধেক করে। |
| Linear — O(n) | Cost grows in proportion to n. | n-এর সাথে সমানুপাতিক। |
| Linearithmic — O(n log n) | Common for fast sorts. | দ্রুত sort-এর সাধারণ complexity। |
| Quadratic — O(n²) | Cost grows with the square of n. | n²-এর হারে বাড়ে। |
| Exponential — O(2ⁿ) | Doubles for every extra input. | প্রতি অতিরিক্ত input-এ দ্বিগুণ। |
| Worst / Best / Average | The three cases for analyzing algorithms. | Algorithm বিশ্লেষণের তিন ক্ষেত্র। |
| Amortized | Average cost over a sequence of operations. | একটি ক্রমিক operation-এর গড় cost। |
Summary — Module 30
Big-O constant আর lower-order term লুকায়; দেখায় cost কীভাবে বাড়ে। Classes ও n-budget জানাই algorithmic thinking-এর ভিত্তি।