WEEK 2 • استراتيجيات الخوارزميات

Divide & Conquer

فرّق تسد

إيه هي استراتيجية Divide & Conquer؟

🎯 الفكرة الأساسية

📖 تشبيه الكتاب الكبير

تخيل عندك كتاب ضخم ومحتاج ترتبه. بدل ما ترتبه كله مرة واحدة:

  1. قسّم الكتاب لفصول
  2. قسّم كل فصل لـ صفحات
  3. رتّب كل صفحة لوحدها (سهل!)
  4. ادمج الصفحات المرتبة ← فصل مرتب
  5. ادمج الفصول ← كتاب مرتب!

📐 الثلاث خطوات

✂️
1. Divide

قسّم المشكلة لمشاكل أصغر

⚔️
2. Conquer

حل كل مشكلة صغيرة (recursively)

🔗
3. Combine

ادمج الحلول الصغيرة

🌟 أمثلة شهيرة

  • Merge Sort - ترتيب بالدمج
  • Quick Sort - ترتيب سريع
  • Binary Search - البحث الثنائي
  • Strassen's Matrix Multiplication

Merge Sort

ترتيب الدمج - المثال الكلاسيكي

📝 إزاي Merge Sort بيشتغل؟

1. Divide: قسّم المصفوفة على نصين. كرر لحد ما كل قطعة تبقى عنصر واحد.
2. Conquer: عنصر واحد = مترتب بالتعريف! (Base Case)
3. Combine (Merge): ادمج القطعتين المترتبتين في قطعة واحدة مترتبة.

مثال: ترتيب [38, 27, 43, 3, 9, 82, 10]

38
27
43
3
9
82
10
↓ Divide ↓
38
27
43
3
9
82
10
↓ Divide ↓
38
27
43
3
9
82
10
↓ Divide to single elements (Base Case) ↓
38
27
43
3
9
82
10
↑ Merge (Combine) ↑
27
38
3
43
9
82
10
↑ Merge ↑
3
27
38
43
9
10
82
↑ Final Merge ↑
3
9
10
27
38
43
82

✓ مترتبة!

عملية الـ Merge بالتفصيل

الـ Merge هو قلب الخوارزمية. بناخد قطعتين مترتبتين وندمجهم:

مثال: دمج [3, 27] مع [9, 43]

Step 1: قارن 3 و 9 → 3 أصغر → [3]
Step 2: قارن 27 و 9 → 9 أصغر → [3, 9]
Step 3: قارن 27 و 43 → 27 أصغر → [3, 9, 27]
Step 4: خلاص، 43 الباقي → [3, 9, 27, 43]

💡 الفكرة:

  • • دايماً بنقارن أول عنصر من كل قائمة
  • • الأصغر بيروح للنتيجة
  • • بنكرر لحد ما قائمة تخلص
  • • اللي فاضل بيتضاف في الآخر

التعقيد

Time

O(n log n)

log n: عدد مستويات التقسيم

n: عمليات الـ merge في كل مستوى

أفضل، متوسط، وأسوأ حالة كلهم O(n log n)!

Space

O(n)

محتاجين array مؤقتة للـ merge

⚠️ مش in-place زي Selection Sort

+ O(log n) للـ call stack

INTERACTIVE

Merge Sort Demo

Click "Sort" to see Merge Sort in action.

Implementation

mergeSort.js
function mergeSort(arr) {
  // Base Case
  if (arr.length <= 1) return arr;
  
  // Divide
  const mid = Math.floor(arr.length / 2);
  const left = mergeSort(arr.slice(0, mid));
  const right = mergeSort(arr.slice(mid));
  
  // Combine (Merge)
  return merge(left, right);
}

function merge(left, right) {
  const result = [];
  let i = 0, j = 0;
  
  while (i < left.length && j < right.length) {
    if (left[i] < right[j]) {
      result.push(left[i++]);
    } else {
      result.push(right[j++]);
    }
  }
  
  return result.concat(left.slice(i), right.slice(j));
}

شرح الكود 📖

سطر 3: Base Case - لو عنصر واحد أو فاضي، ارجعه زي ما هو
سطر 6-8: قسّم على نصين وكرر recursively
سطر 11: ادمج النصين المترتبين
merge(): قارن أول عنصر من كل قائمة، حط الأصغر في النتيجة
سطر 25: اللي فاضل من أي قائمة، ضيفه في الآخر