diff --git a/lessons/mergesort.md b/lessons/mergesort.md index 52eab50f..663d5707 100644 --- a/lessons/mergesort.md +++ b/lessons/mergesort.md @@ -5,3 +5,193 @@ order: "8E" section: "Recursion" description: "learn Recursion from scratch" --- + +# 🧩 Merge Sort – Complete Notes + +> **Merge Sort** is a sorting algorithm based on the **Divide and Conquer** paradigm. +It divides the input array into smaller subarrays, recursively sorts them, and then merges the sorted subarrays to produce the final sorted array. + +--- + +## 📌 Why Merge Sort? +- Guaranteed performance +- Stable sorting algorithm +- Efficient for large datasets +- Ideal for external sorting (files, linked lists) + +--- + +## ⚙️ Core Idea (Divide and Conquer) + +1. **Divide** the array into two halves +2. **Recursively sort** each half +3. **Merge** the sorted halves + + +--- + +## 🔍 Step-by-Step Example + +### Given Array +[38, 27, 43, 3, 9, 82, 10] + +### Step 1: Divide Phase + +[38, 27, 43, 3] [9, 82, 10] + +[38, 27] [43, 3] [9, 82] [10] + +[38] [27] [43] [3] [9] [82] [10] + +--- + +### Step 2: Merge Phase (Bottom-Up) + +[38] + [27] → [27, 38] +[43] + [3] → [3, 43] +[9] + [82] → [9, 82] + + +[27, 38] + [3, 43] → [3, 27, 38, 43] +[9, 82] + [10] → [9, 10, 82] + +Final Sorted Array: +[3, 9, 10, 27, 38, 43, 82] + +### 🧠 Algorithm (Pseudocode) + + + MergeSort(arr): + if length(arr) ≤ 1: + return arr + + mid = length(arr) / 2 + left = MergeSort(arr[0..mid]) + right = MergeSort(arr[mid+1..end]) + + return Merge(left, right) + + +### 🔗 Merge Procedure + + + Merge(left, right): + result = empty array + + while left and right are not empty: + if left[0] ≤ right[0]: + add left[0] to result + else: + add right[0] to result + + append remaining elements of left + append remaining elements of right + + return result + + +### 💻 Java Implementation + + + class MergeSort { + + void merge(int[] arr, int left, int mid, int right) { + int n1 = mid - left + 1; + int n2 = right - mid; + + int[] L = new int[n1]; + int[] R = new int[n2]; + + for (int i = 0; i < n1; i++) + L[i] = arr[left + i]; + + for (int j = 0; j < n2; j++) + R[j] = arr[mid + 1 + j]; + + int i = 0, j = 0, k = left; + + while (i < n1 && j < n2) { + if (L[i] <= R[j]) + arr[k++] = L[i++]; + else + arr[k++] = R[j++]; + } + + while (i < n1) + arr[k++] = L[i++]; + + while (j < n2) + arr[k++] = R[j++]; + } + + void sort(int[] arr, int left, int right) { + if (left < right) { + int mid = left + (right - left) / 2; + + sort(arr, left, mid); + sort(arr, mid + 1, right); + merge(arr, left, mid, right); + } + } + } + + +## ⏱️ Time and Space Complexity + +### ⏱️ Time Complexity + +| Case | Complexity | +|---------|------------| +| Best | O(n log n) | +| Average | O(n log n) | +| Worst | O(n log n) | + +### 📦 Space Complexity + +| Property | Value | +|--------------|-------| +| Extra Space | O(n) | +| In-place | ❌ No | +| Stable | ✅ Yes | + +--- + +## ✅ Advantages + +- Guaranteed performance +- Stable sorting +- Suitable for large datasets +- Efficient for linked lists and external sorting + +--- + +## ❌ Disadvantages + +- Requires additional memory +- Slower than Quick Sort for small inputs +- Not an in-place algorithm + +--- + +## 🎯 Interview Quick Points + +- Based on **Divide and Conquer** +- Always runs in **O(n log n)** +- **Stable**, but **not in-place** +- Preferred in **external sorting** + +--- + +## 📌 When to Use Merge Sort? + +✔ Large datasets +✔ Stability is required +✔ Linked lists +✔ File-based data sorting + +--- + +## 📝 Summary + +> Merge Sort is a **stable, efficient, and predictable** sorting algorithm. +Its guaranteed time complexity makes it suitable for large-scale and real-world applications despite higher memory usage.