Bölüm 11: Böl ve Fethet Yaklaşımı
Giriş
Öğrenme Çıktıları
Böl ve fethet (divide and conquer) yaklaşımının adımlarını açıklamak; bir problemin bu yaklaşıma uygun olup olmadığına karar vermek.
Özyineleme bağıntısını (recurrence) kurmak; özyineleme ağacı ve ana teorem (master theorem) ile çözmek.
Quickhull ile dışbükey örtüyü ve şerit yöntemiyle en yakın nokta çiftini adım adım bulmak.
Karatsuba (tam sayı) ve Strassen (matris) çarpımının, bir özyinelemeli çağrıyı eksilterek nasıl kazanç sağladığını göstermek.
Paradigma
Böl–Parçala–Yönet Paradigması
Karmaşık problemleri çözmek için kullanılan etkili bir yöntemdir (divide and conquer, böl ve fethet / böl ve yönet). Şu adımları izler:
- Böl: karmaşık problemi daha küçük, yönetilebilir alt problemlere böl.
- Parçala: alt problemleri, doğrudan çözülebilecek kadar küçülene dek bölmeye devam et (özyineleme).
- Yönet: her bir alt problemi ayrı ayrı çöz.
- Birleştir: alt problemlerin çözümlerini birleştirerek asıl çözümü kur.
Paradigma
Neden Böl ve Fethet?
- Karmaşık problemi küçük ve yönetilebilir parçalara ayırır; problem daha anlaşılır hale gelir, çözümü kolaylaşır.
- Alt problemlerin çözüm yöntemi (aynı fonksiyon) her düzeyde tekrar kullanılır: kısa ve yeniden kullanılabilir kod.
- Sıralama, arama, hesaplamalı geometri, büyük sayı ve matris aritmetiği, yapay zekâ oyunları gibi alanlarda kullanılır.
Avantajlar
- Çoğu zaman asimptotik kazanç: O(n²) → O(n log n), O(n) → O(log n).
- Bağımsız alt problemler paralel çözülebilir (Bölüm 10).
- Alt problemler küçüldükçe önbelleğe sığar: iyi bellek yerelliği.
- Doğruluk kanıtı tümevarımla kolaydır.
Dezavantajlar
- Özyineleme yükü: çağrı yığını, ek bellek (ör. birleştirerek sıralamada O(n)).
- Alt problemler örtüşüyorsa aynı iş tekrar tekrar yapılır → üstel süre.
- Küçük n için sabit çarpanlar ağır basar; pratikte bir eşiğin altında basit yönteme geçilir.
Paradigma
Genel Şablon ve Bağıntı
Sonuc bolVeFethet(Problem p) {
if (p.boyut() <= ESIK)
return dogrudanCoz(p); // taban durumu
Problem[] alt = bol(p); // a alt problem, boyut n/b
Sonuc[] cozum = new Sonuc[alt.length];
for (int i = 0; i < alt.length; i++)
cozum[i] = bolVeFethet(alt[i]); // yönet: özyineleme
return birlestir(cozum); // birleştir
}T(n) = a·T(n/b) + f(n)
a: alt problem sayısı · n/b: alt problem boyutu · f(n): bölme + birleştirme maliyeti
- Taban durumu olmadan özyineleme bitmez.
- Bölme dengeli olmalı: n/2 + n/2 iyi, 1 + (n − 1) kötü.
- Hız kazancı genellikle a'yı azaltmaktan (Karatsuba, Strassen) ya da f(n)'yi küçültmekten gelir.
Paradigma
Klasik Böl ve Fethet Algoritmaları
| Algoritma | Böl | Birleştir | Bağıntı | Süre |
|---|---|---|---|---|
| İkili arama | ortadaki elemana bak, bir yarıyı at | yok | T(n/2) + O(1) | O(log n) |
| Birleştirerek sıralama | diziyi ortadan ikiye böl | sıralı yarıları birleştir | 2T(n/2) + O(n) | O(n log n) |
| Hızlı sıralama | pivota göre bölümle | yok (yerinde) | T(k) + T(n−k−1) + O(n) | ort. O(n log n) |
| Hızlı üs alma | xⁿ = (x⌊n/2⌋)²·(x) | kare al | T(n/2) + O(1) | O(log n) |
| Quickhull | en uzak noktayla üçgen | örtü parçalarını ekle | T(n₁) + T(n₂) + O(n) | ort. O(n log n) |
| En yakın nokta çifti | x'e göre ortadan böl | orta şeridi tara | 2T(n/2) + O(n) | O(n log n) |
| Karatsuba | sayıyı iki yarıya böl | 3 çarpımı topla | 3T(n/2) + O(n) | O(n1,585) |
| Strassen | matrisi 4 bloğa böl | 7 çarpımı topla | 7T(n/2) + O(n²) | O(n2,807) |
Özyineleme Bağıntıları
Özyineleme Ağacı (Recursion Tree)
Her düğüm bir çağrının kendi işini (bölme + birleştirme) gösterir. Düzey toplamları alt alta toplanınca T(n) bulunur.
T(n) = 2T(n/2) + n (birleştirerek sıralama): her düzeyin toplamı n, düzey sayısı log₂ n → Θ(n log n).
T(n) = 3T(n/2) + n (Karatsuba): düzey toplamları 1,5 kat büyür; en çok iş yapraklarda → Θ(nlog₂3).
T(n) = T(n/2) + 1 (ikili arama, hızlı üs alma): tek dal, her düzey O(1) → Θ(log n).
Özyineleme Bağıntıları
Ana Teorem (Master Theorem)
a ≥ 1, b > 1 olmak üzere T(n) = a·T(n/b) + f(n). Kritik üs c* = logb a: yaprak sayısı nc* olur. f(n) ile nc* karşılaştırılır:
| Durum | Koşul | Sonuç | Yorum |
|---|---|---|---|
| 1 | f(n) = O(nc* − ε), ε > 0 | Θ(nc*) | yapraklar baskın |
| 2 | f(n) = Θ(nc*) | Θ(nc* · log n) | her düzey eşit pay |
| 3 | f(n) = Ω(nc* + ε) ve a·f(n/b) ≤ k·f(n), k < 1 | Θ(f(n)) | kök baskın |
Özyineleme Bağıntıları
Ana Teorem Uygulamaları
| Algoritma | a | b | f(n) | nlogb a | Durum | T(n) |
|---|---|---|---|---|---|---|
| İkili arama, hızlı üs alma | 1 | 2 | 1 | n⁰ = 1 | 2 | Θ(log n) |
| Birleştirerek sıralama, en yakın çift | 2 | 2 | n | n | 2 | Θ(n log n) |
| Karatsuba | 3 | 2 | n | n1,585 | 1 | Θ(n1,585) |
| Saf blok matris çarpımı | 8 | 2 | n² | n³ | 1 | Θ(n³) |
| Strassen | 7 | 2 | n² | n2,807 | 1 | Θ(n2,807) |
| Ağaç gezinme (dengeli) | 2 | 2 | 1 | n | 1 | Θ(n) |
| T(n) = 2T(n/2) + n² | 2 | 2 | n² | n | 3 | Θ(n²) |
Karatsuba ve Strassen'in tüm kazancı a'yı bir azaltmaktan gelir: 4 → 3 ve 8 → 7. Durum 1'de üs doğrudan logb a'dır.
Temel Örnekler
İkili Arama (Binary Search): 23'ü Ara
alt = 0, ust = 9 → orta = 4: dizi[4] = 16 < 23 → sol yarı atılır, alt = 5.
alt = 5, ust = 9 → orta = 7: dizi[7] = 56 > 23 → sağ yarı atılır, ust = 6.
alt = 5, ust = 6 → orta = 5: dizi[5] = 23 = 23 → bulundu. Yalnızca 3 karşılaştırma (doğrusal aramada 6).
int ara(int[] dizi, int alt, int ust, int aranan) { if (alt > ust) return -1; // boş aralık int orta = (alt + ust) / 2; if (dizi[orta] == aranan) return orta; if (dizi[orta] < aranan) return ara(dizi, orta + 1, ust, aranan); // sağ yarı return ara(dizi, alt, orta - 1, aranan); // sol yarı }
- Böl: ortadaki eleman. Yönet: yalnızca bir yarıda devam. Birleştir: yok.
- T(n) = T(n/2) + O(1) = O(log n); dizi sıralı olmalı.
- Tek dallı olduğu için "azalt ve fethet" (decrease and conquer) de denir.
Temel Örnekler
Birleştirerek Sıralama (Merge Sort)
Dizi: [38, 27, 43, 3, 9, 82, 10], n = 7.
Böl: orta = (0 + 6)/2 = 3 → [38 27 43 3] ve [9 82 10].
Yarılar yeniden bölünür: [38 27] [43 3] [9 82] [10].
Tek elemanlı diziler zaten sıralıdır: taban durumu.
Birleştir: ikililer sıralı birleşir: [27 38] [3 43] [9 82] [10].
[3 27 38 43] ve [9 10 82]: her birleştirme, iki yarının uzunluk toplamı kadar adım.
Son birleştirme: [3 9 10 27 38 43 82]. Her düzey O(n), ⌈log₂ 7⌉ = 3 düzey.
Temel Örnekler
Birleştirerek Sıralama: Kod ve Analiz
void birlestirSirala(int[] dizi, int alt, int ust) { if (alt >= ust) return; // taban: 0-1 eleman int orta = (alt + ust) / 2; birlestirSirala(dizi, alt, orta); // sol yarı birlestirSirala(dizi, orta + 1, ust); // sağ yarı birlestir(dizi, alt, orta, ust); // birleştir: O(n) } void birlestir(int[] dizi, int alt, int orta, int ust) { int[] t = new int[ust - alt + 1]; int i = alt, j = orta + 1, k = 0; while (i <= orta && j <= ust) t[k++] = (dizi[i] <= dizi[j]) ? dizi[i++] : dizi[j++]; while (i <= orta) t[k++] = dizi[i++]; while (j <= ust) t[k++] = dizi[j++]; System.arraycopy(t, 0, dizi, alt, t.length); }
- İş birleştirme adımında yapılır; bölme O(1).
- T(n) = 2T(n/2) + Θ(n) → durum 2 → Θ(n log n); en iyi, ortalama ve en kötü durumda aynı.
dizi[i] <= dizi[j]eşitlikte soldakini alır → kararlı (stable).- Ek bellek: O(n) geçici dizi; çağrı yığını O(log n).
- Ayrıntılı görselleştirme: Bölüm 2.
Temel Örnekler
Hızlı Sıralama (Quick Sort)
Dizi [10 80 30 90 40 50 70]; Lomuto bölümlemesi: son eleman pivot (70).
bölümle(dizi, 0, 6), pivot 70 → indis 4'e yerleşti. Sol: [10 30 40 50], sağ: [90 80].
bölümle(dizi, 0, 3), pivot 50 → indis 3'e yerleşti. Sol: [10 30 40], sağ: [—]. Dengesiz bölme!
bölümle(dizi, 0, 2), pivot 40 → indis 2'ye yerleşti. Sol: [10 30], sağ: [—]. Dengesiz bölme!
bölümle(dizi, 0, 1), pivot 30 → indis 1'e yerleşti. Sol: [10], sağ: [—]. Dengesiz bölme!
bölümle(dizi, 5, 6), pivot 80 → indis 5'e yerleşti. Sol: [—], sağ: [90]. Dengesiz bölme!
Sıralı: [10 30 40 50 70 80 90]. Birleştirme adımı yok; iş bölümlemede yapılır.
Temel Örnekler · Kodu adım adım çalıştır
Hızlı Üs Alma: 3¹³ İzleme
long us(long x, int n) { if (n == 0) return 1; // taban long y = us(x, n / 2); if (n % 2 == 0) return y * y; // çift return x * y * y; // tek }
Saf yöntem 12 çarpım; bu yöntem 4 düzeyde en çok 2'şer çarpım → O(log n): T(n) = T(n/2) + O(1).
us(3, 13) çağrıldı → önce us(3, 6) hesaplanmalı (n/2 = 6).
us(3, 6) çağrıldı → önce us(3, 3) hesaplanmalı (n/2 = 3).
us(3, 3) çağrıldı → önce us(3, 1) hesaplanmalı (n/2 = 1).
us(3, 1) çağrıldı → önce us(3, 0) hesaplanmalı (n/2 = 0).
n = 0 → taban durumu: 3⁰ = 1 döner.
us(3, 1): y = 1; 1 tek → x·y·y = 3·1·1 = 3.
us(3, 3): y = 3; 3 tek → x·y·y = 3·3·3 = 27.
us(3, 6): y = 27; 6 çift → y·y = 27·27 = 729.
us(3, 13): y = 729; 13 tek → x·y·y = 3·729·729 = 1594323.
Temel Örnekler
Ne Zaman Uygun Değil? Örtüşen Alt Problemler
long fib(int n) { if (n < 2) return n; return fib(n - 1) + fib(n - 2); }
- F(5) için 15 çağrı: F(3) 2 kez, F(2) 3 kez hesaplanır.
- Alt problemler bağımsız değil, örtüşüyor → T(n) = T(n−1) + T(n−2) + O(1) = O(φⁿ) ≈ O(1,618ⁿ).
- Çözüm: sonuçları sakla → dinamik programlama (Bölüm 6), O(n).
Dışbükey Örtü
Dışbükey Örtü (Convex Hull)
- Düzlemde n noktalı bir küme S verilsin. S'nin dışbükey örtüsü, S'yi içeren en küçük dışbükey çokgendir.
- Sezgi: noktalara çivi çakıp etrafına bir lastik bant geçirin; bandın aldığı şekil örtüdür.
- Örtünün köşeleri S'nin noktalarıdır; çıktı bu köşelerin (saat yönünün tersine) sıralı listesidir.
- Dışbükey: içindeki herhangi iki noktayı birleştiren doğru parçası tamamen çokgenin içindedir.
Dışbükey Örtü
Quickhull Algoritması
- x'i en küçük (A) ve en büyük (B) noktaları bul; ikisi de örtüdedir.
- AB doğrusu ile noktaları iki alt kümeye ayır: doğrunun üstü (solu) ve altı (sağı).
- Bir alt kümede AB'ye en uzak C noktasını bul; C örtüdedir.
- ACB üçgeninin içindeki noktaları yok say: örtüde olamazlar.
- AC'nin dışında kalanlar ve CB'nin dışında kalanlar için özyinele.
- Hiç nokta kalmayınca dur; bulunan noktalar örtüyü oluşturur.
Adım 1–2: en soldaki A ve en sağdaki B örtüdedir; AB doğrusu noktaları iki kümeye ayırır (üst / alt).
Adım 3–5: üst kümede AB'ye en uzak C (13,27) örtüdedir. ACB üçgeninin içindeki 4 nokta elenir; AC ve CB dışında kalanlarla özyineleme.
Adım 6: dışarıda nokta kalmayana dek özyineleme → 7 köşeli örtü.
Hızlı sıralamaya benzer (adı da buradan): "pivot" en uzak nokta, bölümleme üçgenin iki kenarına göre yapılır.
Dışbükey Örtü
Geometri: Yönelim Testi ve Uzaklık
Quickhull yalnızca tam sayı çarpımıyla çalışır; açı, karekök, bölme gerekmez:
long capraz(Nokta A, Nokta B, Nokta P) { return (long)(B.x - A.x) * (P.y - A.y) - (long)(B.y - A.y) * (P.x - A.x); }
- capraz > 0: P, A→B'nin solunda; < 0: sağında; = 0: aynı doğruda.
- |capraz| = 2 × (ABP üçgeninin alanı) = |AB| × uzaklık. |AB| sabit olduğundan en uzak nokta = en büyük capraz.
Dışbükey Örtü · Kodu adım adım çalıştır
Quickhull: Kod İzleme
void quickHull(List<Nokta> P) { Nokta A = enSol(P), B = enSag(P); ortu.add(A); ortu.add(B); bul(solda(P, A, B), A, B); // üst küme bul(solda(P, B, A), B, A); // alt küme } void bul(List<Nokta> S, Nokta A, Nokta B) { if (S.isEmpty()) return; // AB örtü kenarı Nokta C = enUzak(S, A, B); // max capraz ortu.add(C); bul(solda(S, A, C), A, C); // AC'nin dışı bul(solda(S, C, B), C, B); // CB'nin dışı } // ACB üçgeninin içi elenir
En sol A = (2,18), en sağ B = (35,11) örtüye eklenir.
AB'nin solunda (üst) 8, sağında (alt) 6 nokta. Önce üst küme.
|S| = 8: en uzak C = (13,27) örtüye girer. Üçgen içinde 4 nokta elenir; AC dışında 1, CB dışında 2 nokta.
|S| = 1: en uzak C = (4,25) örtüye girer. Üçgen içinde 0 nokta elenir; AC dışında 0, CB dışında 0 nokta.
S boş → (2,18)–(4,25) bir örtü kenarıdır; geri dön.
S boş → (4,25)–(13,27) bir örtü kenarıdır; geri dön.
|S| = 2: en uzak C = (28,23) örtüye girer. Üçgen içinde 1 nokta elenir; AC dışında 0, CB dışında 0 nokta.
S boş → (13,27)–(28,23) bir örtü kenarıdır; geri dön.
S boş → (28,23)–(35,11) bir örtü kenarıdır; geri dön.
|S| = 6: en uzak C = (20,2) örtüye girer. Üçgen içinde 4 nokta elenir; AC dışında 0, CB dışında 1 nokta.
S boş → (35,11)–(20,2) bir örtü kenarıdır; geri dön.
|S| = 1: en uzak C = (10,5) örtüye girer. Üçgen içinde 0 nokta elenir; AC dışında 0, CB dışında 0 nokta.
S boş → (20,2)–(10,5) bir örtü kenarıdır; geri dön.
S boş → (10,5)–(2,18) bir örtü kenarıdır; geri dön.
Bitti: 7 köşe bulundu, 9 nokta elendi. Toplam 12 bul çağrısı.
Dışbükey Örtü
Quickhull: 104 Noktalı Örnek
104 nokta. En sol (-14,46) ve en sağ (106,20) birleştirilir; üstte 71, altta 31 nokta.
(-14,46)→(106,20) için en uzak: (54,120); üçgen içindeki 56 nokta elendi. Aday kaldı: 45.
(-14,46)→(54,120) için en uzak: (8,84); üçgen içindeki 2 nokta elendi. Aday kaldı: 42.
(-14,46)→(8,84) için en uzak: (-4,69); üçgen içindeki 0 nokta elendi. Aday kaldı: 41.
(8,84)→(54,120) için en uzak: (42,111); üçgen içindeki 1 nokta elendi. Aday kaldı: 39.
(54,120)→(106,20) için en uzak: (104,74); üçgen içindeki 6 nokta elendi. Aday kaldı: 32.
(54,120)→(104,74) için en uzak: (77,103); üçgen içindeki 0 nokta elendi. Aday kaldı: 31.
(106,20)→(-14,46) için en uzak: (11,-25); üçgen içindeki 25 nokta elendi. Aday kaldı: 5.
(106,20)→(11,-25) için en uzak: (88,-5); üçgen içindeki 4 nokta elendi. Aday kaldı: 0.
Bitti: 104 noktanın örtüsü 10 köşe. Her adımda noktaların çoğu elendiği için iş hızla azalır.
Dışbükey Örtü
Quickhull Analizi ve Diğer Örtü Algoritmaları
- Her çağrı S'yi bir kez tarar (en uzak nokta + iki bölümleme): O(|S|).
- T(n) = T(n₁) + T(n₂) + O(n), n₁ + n₂ ≤ n − 1.
- Ortalama (dengeli bölmeler, çok nokta elenir): O(n log n); rastgele düzgün dağılımda çoğu zaman daha da hızlı.
- En kötü durum: her adımda yalnızca bir nokta ayrılır → T(n) = T(n − 1) + O(n) = O(n²).
- Çıktıya duyarlı sınır: h köşeli örtü için O(n·h).
| Algoritma | Süre |
|---|---|
| Kaba kuvvet (her kenar adayı) | O(n³) |
| Jarvis yürüyüşü (gift wrapping) | O(n·h) |
| Graham taraması | O(n log n) |
| Andrew monoton zincir | O(n log n) |
| Quickhull | ort. O(n log n), en kötü O(n²) |
| Chan | O(n log h) |
En Yakın Nokta Çifti
En Yakın Nokta Çifti (Closest Pair)
Düzlemde n nokta verilsin; aralarındaki Öklid uzaklığı d(p, q) = √((pₓ − qₓ)² + (py − qy)²) en küçük olan çifti bulun.
double kabaKuvvet(List<Nokta> p) { double enAz = Double.MAX_VALUE; for (int i = 0; i < p.size(); i++) for (int j = i + 1; j < p.size(); j++) enAz = Math.min(enAz, mesafe(p.get(i), p.get(j))); return enAz; }
- Kaba kuvvet: n(n − 1)/2 çift → O(n²). n = 10⁶ için ≈ 5·10¹¹ uzaklık.
- Tek boyutta kolay: sırala, yalnızca komşuları karşılaştır → O(n log n).
- İki boyutta x'e göre sıralı komşular yetmez; böl ve fethet ile O(n log n) mümkün.
En Yakın Nokta Çifti
Böl ve Fethet: Orta Şerit
- Noktaları bir kez x'e ve bir kez y'ye göre sırala.
- Böl: ortadaki noktanın x'inden geçen L doğrusu ile iki yarı.
- Yönet: iki yarıda özyinelemeyle δL ve δR; δ = min(δL, δR).
- Birleştir: daha yakın bir çift varsa L'yi keser → yalnızca |x − L| < δ olan şerit noktalarına bak.
- Şeridi y sırasıyla tara; her nokta yalnızca y farkı δ'dan küçük olan sonrakilerle karşılaştırılır.
En Yakın Nokta Çifti · Kodu adım adım çalıştır
En Yakın Çift: Kod İzleme
double enYakin(List<Nokta> X, List<Nokta> Y) { int n = X.size(), orta = n / 2; if (n <= 3) return kabaKuvvet(X); Nokta m = X.get(orta); // Ysol/Ysag: Y'nin yarıları double dSol = enYakin(X.subList(0, orta), Ysol); double dSag = enYakin(X.subList(orta, n), Ysag); double d = Math.min(dSol, dSag); List<Nokta> s = new ArrayList<>(); // şerit for (Nokta p : Y) // y sırası if (Math.abs(p.x - m.x) < d) s.add(p); for (int i = 0; i < s.size(); i++) { Nokta p = s.get(i); for (int j = i + 1; j < s.size() && s.get(j).y - p.y < d; j++) d = Math.min(d, mesafe(p, s.get(j))); } return d; }
n = 10 > 3 → orta = 5, m = (12,10). Sol: 5, sağ: 5 nokta.
n = 5 > 3 → orta = 2, m = (5,1). Sol: 2, sağ: 3 nokta.
n = 2 ≤ 3 → kaba kuvvet: (2,3), (3,4). En yakın (2,3)–(3,4), d = 1,41.
n = 3 ≤ 3 → kaba kuvvet: (5,1), (7,7), (12,30). En yakın (5,1)–(7,7), d = 6,32.
İki yarı döndü: dSol = 1,41, dSag = 6,32 → d = 1,41.
Şerit |x − 5| < 1,41: [(5,1)]; tek nokta → karşılaştırma yok. Dönüş: 1,41.
n = 5 > 3 → orta = 2, m = (27,27). Sol: 2, sağ: 3 nokta.
n = 2 ≤ 3 → kaba kuvvet: (12,10), (17,17). En yakın (12,10)–(17,17), d = 8,60.
n = 3 ≤ 3 → kaba kuvvet: (27,27), (28,27), (40,50). En yakın (27,27)–(28,27), d = 1,00.
İki yarı döndü: dSol = 8,60, dSag = 1,00 → d = 1,00.
Şerit |x − 27| < 1,00: [(27,27)]; tek nokta → karşılaştırma yok. Dönüş: 1,00.
İki yarı döndü: dSol = 1,41, dSag = 1,00 → d = 1,00.
Şerit |x − 12| < 1,00: [(12,10), (12,30)]; y farkı d'den büyük → hiç karşılaştırma yok. Dönüş: 1,00.
En Yakın Nokta Çifti
En Yakın Çift: Analiz
| Adım | Maliyet | Not |
|---|---|---|
| x ve y'ye göre ön sıralama | O(n log n) | yalnızca bir kez, özyinelemeden önce |
| Bölme (X ikiye, Y'yi sırayı koruyarak Ysol/Ysag'ye) | O(n) | yeniden sıralama yok |
| Şeridi kurma | O(n) | Y zaten y'ye göre sıralı |
| Şeridi tarama | O(7n) = O(n) | her nokta ≤ 7 komşu |
| Toplam | O(n log n) | T(n) = 2T(n/2) + O(n) |
Karatsuba Çarpımı
Karatsuba: 4 Çarpım Yerine 3
n basamaklı x, y sayılarını m = ⌊n/2⌋ noktasından böl: x = a·10m + b, y = c·10m + d.
4 çarpım: ac, ad, bc, bd
T(n) = 4T(n/2) + O(n) = O(n²) → kazanç yok!
⇒ ad + bc = (a + b)(c + d) − ac − bd
3 çarpım: z2 = ac, z0 = bd, z1 = (a + b)(c + d)
T(n) = 3T(n/2) + O(n) = O(n1,585)
| Örnek: 1234 · 5678 (m = 2, 10m = 100) | |
|---|---|
| a = 12, b = 34, c = 56, d = 78 | z2 = 12·56 = 672 · z0 = 34·78 = 2652 |
| z1 = (12 + 34)(56 + 78) = 46·134 = 6164 | z1 − z2 − z0 = 6164 − 672 − 2652 = 2840 (= ad + bc) |
| 672·10⁴ + 2840·10² + 2652 = 6 720 000 + 284 000 + 2652 = 7 006 652 ✓ | |
Karatsuba Çarpımı · Kodu adım adım çalıştır
Karatsuba: 1234 · 5678 İzleme
karatsuba(1234, 5678): n = 4, p = 100 → a = 12, b = 34, c = 56, d = 78. Üç çağrı: (34, 78), (46, 134), (12, 56).
karatsuba(34, 78): n = 2, p = 10 → a = 3, b = 4, c = 7, d = 8. Üç çağrı: (4, 8), (7, 15), (3, 7).
4 · 8: tek basamaklı çarpan var → taban, doğrudan 32.
7 · 15: tek basamaklı çarpan var → taban, doğrudan 105.
3 · 7: tek basamaklı çarpan var → taban, doğrudan 21.
21·100 + (105 − 21 − 32)·10 + 32 = 2100 + 520 + 32 = 2652.
karatsuba(46, 134): n = 3, p = 10 → a = 4, b = 6, c = 13, d = 4. Üç çağrı: (6, 4), (10, 17), (4, 13).
6 · 4: tek basamaklı çarpan var → taban, doğrudan 24.
karatsuba(10, 17): n = 2, p = 10 → a = 1, b = 0, c = 1, d = 7. Üç çağrı: (0, 7), (1, 8), (1, 1).
0 · 7: tek basamaklı çarpan var → taban, doğrudan 0.
1 · 8: tek basamaklı çarpan var → taban, doğrudan 8.
1 · 1: tek basamaklı çarpan var → taban, doğrudan 1.
1·100 + (8 − 1 − 0)·10 + 0 = 100 + 70 + 0 = 170.
4 · 13: tek basamaklı çarpan var → taban, doğrudan 52.
52·100 + (170 − 52 − 24)·10 + 24 = 5200 + 940 + 24 = 6164.
karatsuba(12, 56): n = 2, p = 10 → a = 1, b = 2, c = 5, d = 6. Üç çağrı: (2, 6), (3, 11), (1, 5).
2 · 6: tek basamaklı çarpan var → taban, doğrudan 12.
3 · 11: tek basamaklı çarpan var → taban, doğrudan 33.
1 · 5: tek basamaklı çarpan var → taban, doğrudan 5.
5·100 + (33 − 5 − 12)·10 + 12 = 500 + 160 + 12 = 672.
672·10000 + (6164 − 672 − 2652)·100 + 2652 = 6720000 + 284000 + 2652 = 7006652.
long karatsuba(long x, long y) { if (x < 10 || y < 10) return x * y; // taban int n = Math.max(basamak(x), basamak(y)); long p = (long) Math.pow(10, n / 2); long a = x / p, b = x % p; // x = a·p + b long c = y / p, d = y % p; // y = c·p + d long z0 = karatsuba(b, d); long z1 = karatsuba(a + b, c + d); long z2 = karatsuba(a, c); return z2 * p * p + (z1 - z2 - z0) * p + z0; }
Karatsuba Çarpımı
Karatsuba Analizi
- T(n) = 3T(n/2) + O(n) → durum 1 → Θ(nlog₂3) ≈ Θ(n1,585).
- Toplama, çıkarma ve 10m ile kaydırma O(n); çarpım sayısını 4'ten 3'e indirmek üssü 2'den 1,585'e düşürür.
- Örnekte 16 çağrı, 11 tek basamaklı çarpım (okul yöntemi 16).
- Küçük sayılarda ek toplamalar yüzünden yavaştır → bir eşik altında okul yöntemi.
- Java
BigInteger.multiplybüyük sayılarda Karatsuba ve Toom-Cook kullanır. Daha hızlıları: Schönhage–Strassen O(n log n log log n), Harvey–van der Hoeven O(n log n) (2019).
| n (basamak) | n² | n1,585 | oran |
|---|---|---|---|
| 10 | 100 | 38 | 2,6× |
| 100 | 10 000 | 1 479 | 6,8× |
| 1 000 | 1,0·106 | 56 871 | 17,6× |
| 10 000 | 1,0·108 | 2,2·106 | 45,7× |
| 1,0·106 | 1,0·1012 | 3,2·109 | 309,2× |
Strassen Çarpımı
Matris Çarpımı: Klasik ve Blok
for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) for (int k = 0; k < n; k++) C[i][j] += A[i][k] * B[k][j];
n² hücrenin her biri n çarpım → n³ çarpım.
A, B, C'yi n/2 × n/2'lik dört bloğa böl:
| C11 = A11·B11 + A12·B21 |
| C12 = A11·B12 + A12·B22 |
| C21 = A21·B11 + A22·B21 |
| C22 = A21·B12 + A22·B22 |
Strassen Çarpımı
Strassen (1969): 8 Yerine 7 Çarpım
| Çarpım | Tanım |
|---|---|
| P1 | A11 · (B12 − B22) |
| P2 | (A11 + A12) · B22 |
| P3 | (A21 + A22) · B11 |
| P4 | A22 · (B21 − B11) |
| P5 | (A11 + A22) · (B11 + B22) |
| P6 | (A12 − A22) · (B21 + B22) |
| P7 | (A11 − A21) · (B11 + B12) |
| Sonuç blokları |
|---|
| C11 = P5 + P4 − P2 + P6 |
| C12 = P1 + P2 |
| C21 = P3 + P4 |
| C22 = P5 + P1 − P3 − P7 |
7 çarpım + 18 blok toplama/çıkarma. Bloklar da Strassen ile özyinelemeli çarpılır; taban 1×1.
Strassen Çarpımı
Strassen Adım Adım: 2 × 2 Örnek
| 1 | 3 |
| 7 | 5 |
| 6 | 8 |
| 4 | 2 |
| P1 | A11 · (B12 − B22) | 1 · (8 − 2) | 6 |
| P2 | (A11 + A12) · B22 | … | |
| P3 | (A21 + A22) · B11 | … | |
| P4 | A22 · (B21 − B11) | … | |
| P5 | (A11 + A22) · (B11 + B22) | … | |
| P6 | (A12 − A22) · (B21 + B22) | … | |
| P7 | (A11 − A21) · (B11 + B12) | … |
P1 = 1 · (8 − 2) = 6.
| P1 | A11 · (B12 − B22) | 1 · (8 − 2) | 6 |
| P2 | (A11 + A12) · B22 | (1 + 3) · 2 | 8 |
| P3 | (A21 + A22) · B11 | … | |
| P4 | A22 · (B21 − B11) | … | |
| P5 | (A11 + A22) · (B11 + B22) | … | |
| P6 | (A12 − A22) · (B21 + B22) | … | |
| P7 | (A11 − A21) · (B11 + B12) | … |
P2 = (1 + 3) · 2 = 8.
| P1 | A11 · (B12 − B22) | 1 · (8 − 2) | 6 |
| P2 | (A11 + A12) · B22 | (1 + 3) · 2 | 8 |
| P3 | (A21 + A22) · B11 | (7 + 5) · 6 | 72 |
| P4 | A22 · (B21 − B11) | … | |
| P5 | (A11 + A22) · (B11 + B22) | … | |
| P6 | (A12 − A22) · (B21 + B22) | … | |
| P7 | (A11 − A21) · (B11 + B12) | … |
P3 = (7 + 5) · 6 = 72.
| P1 | A11 · (B12 − B22) | 1 · (8 − 2) | 6 |
| P2 | (A11 + A12) · B22 | (1 + 3) · 2 | 8 |
| P3 | (A21 + A22) · B11 | (7 + 5) · 6 | 72 |
| P4 | A22 · (B21 − B11) | 5 · (4 − 6) | −10 |
| P5 | (A11 + A22) · (B11 + B22) | … | |
| P6 | (A12 − A22) · (B21 + B22) | … | |
| P7 | (A11 − A21) · (B11 + B12) | … |
P4 = 5 · (4 − 6) = −10.
| P1 | A11 · (B12 − B22) | 1 · (8 − 2) | 6 |
| P2 | (A11 + A12) · B22 | (1 + 3) · 2 | 8 |
| P3 | (A21 + A22) · B11 | (7 + 5) · 6 | 72 |
| P4 | A22 · (B21 − B11) | 5 · (4 − 6) | −10 |
| P5 | (A11 + A22) · (B11 + B22) | (1 + 5) · (6 + 2) | 48 |
| P6 | (A12 − A22) · (B21 + B22) | … | |
| P7 | (A11 − A21) · (B11 + B12) | … |
P5 = (1 + 5) · (6 + 2) = 48.
| P1 | A11 · (B12 − B22) | 1 · (8 − 2) | 6 |
| P2 | (A11 + A12) · B22 | (1 + 3) · 2 | 8 |
| P3 | (A21 + A22) · B11 | (7 + 5) · 6 | 72 |
| P4 | A22 · (B21 − B11) | 5 · (4 − 6) | −10 |
| P5 | (A11 + A22) · (B11 + B22) | (1 + 5) · (6 + 2) | 48 |
| P6 | (A12 − A22) · (B21 + B22) | (3 − 5) · (4 + 2) | −12 |
| P7 | (A11 − A21) · (B11 + B12) | … |
P6 = (3 − 5) · (4 + 2) = −12.
| P1 | A11 · (B12 − B22) | 1 · (8 − 2) | 6 |
| P2 | (A11 + A12) · B22 | (1 + 3) · 2 | 8 |
| P3 | (A21 + A22) · B11 | (7 + 5) · 6 | 72 |
| P4 | A22 · (B21 − B11) | 5 · (4 − 6) | −10 |
| P5 | (A11 + A22) · (B11 + B22) | (1 + 5) · (6 + 2) | 48 |
| P6 | (A12 − A22) · (B21 + B22) | (3 − 5) · (4 + 2) | −12 |
| P7 | (A11 − A21) · (B11 + B12) | (1 − 7) · (6 + 8) | −84 |
P7 = (1 − 7) · (6 + 8) = −84.
| C11 = P5 + P4 − P2 + P6 | 48 + (−10) − 8 + (−12) | 18 |
| C12 = P1 + P2 | 6 + 8 | 14 |
| C21 = P3 + P4 | 72 + (−10) | 62 |
| C22 = P5 + P1 − P3 − P7 | 48 + 6 − 72 − (−84) | 66 |
C = [[18, 14], [62, 66]]. Kontrol: 1·6 + 3·4 = 18, 7·8 + 5·2 = 66 ✓. 7 çarpım kullanıldı (klasik 8).
Strassen Çarpımı
Strassen Analizi ve Pratik
- T(n) = 7T(n/2) + Θ(n²) → durum 1 → Θ(nlog₂7) ≈ Θ(n2,807).
- n = 2k için skaler çarpım: 7k (klasik 8k). n = 1024: 7¹⁰ ≈ 2,8·10⁸, 8¹⁰ ≈ 1,07·10⁹ → yaklaşık 3,8 kat az.
- n 2'nin kuvveti değilse matris sıfırlarla doldurulur (padding).
- Eşik: 18 ek toplama ve geçici matrisler yüzünden küçük n'de yavaş; kütüphaneler n ≲ 64–128'de klasik yönteme geçer.
- Sayısal kararlılık: kayan noktalı sayılarda çıkarma işlemleri hatayı büyütebilir.
- Bellek: her düzeyde geçici bloklar → ek O(n²).
- Kuramsal rekor ω < 2,372 (2024); sabitler çok büyük, pratikte kullanılmaz.
Değerlendirme
Saf Yöntem ve Böl ve Fethet
| Problem | Saf yöntem | Böl ve fethet | Bağıntı |
|---|---|---|---|
| Sıralama | O(n²) (kabarcık) | O(n log n) | 2T(n/2) + n |
| Sıralı dizide arama | O(n) | O(log n) | T(n/2) + 1 |
| Üs alma xⁿ | O(n) çarpım | O(log n) | T(n/2) + 1 |
| Dışbükey örtü | O(n³) | ort. O(n log n) | T(n₁) + T(n₂) + n |
| En yakın nokta çifti | O(n²) | O(n log n) | 2T(n/2) + n |
| Tam sayı çarpımı | O(n²) | O(n1,585) | 3T(n/2) + n |
| Matris çarpımı | O(n³) | O(n2,807) | 7T(n/2) + n² |
Kazancın kaynağı: ya iş dengeli bölünüp her düzey O(n)'de birleştiriliyor (sıralama, en yakın çift) ya da alt problem sayısı azaltılıyor (Karatsuba, Strassen) ya da yarısı atılıyor (arama, üs).
Değerlendirme
Böl ve Fethet, Dinamik Programlama, Açgözlü
| Böl ve fethet | Dinamik programlama | Açgözlü | |
|---|---|---|---|
| Alt problemler | bağımsız | örtüşen | tek bir alt problem kalır |
| Yön | yukarıdan aşağı (özyineleme) | çoğunlukla aşağıdan yukarı (tablo) | adım adım, geri dönüş yok |
| Karar | sabit bölme kuralı | tüm seçenekleri dener, en iyisini saklar | o anda en iyi görüneni seçer |
| Örnek | birleştirerek sıralama, Strassen | Fibonacci, sırt çantası | Dijkstra, Huffman, Kruskal |
Özet
Özet
| Konu | Hatırlanacaklar |
|---|---|
| Paradigma | böl → (parçala) → yönet → birleştir; bağımsız, aynı türden alt problemler; taban durumu şart |
| Analiz | T(n) = aT(n/b) + f(n); özyineleme ağacı; ana teorem: f(n)'yi nlogb a ile karşılaştır |
| Temel örnekler | ikili arama ve hızlı üs O(log n); birleştirerek sıralama O(n log n); hızlı sıralama ort. O(n log n), en kötü O(n²) |
| Quickhull | A, B uçlar; en uzak C (max capraz); üçgen içi elenir; ort. O(n log n), en kötü O(n²) |
| En yakın çift | x'e göre böl; δ = min(δL, δR); 2δ şeritte ≤ 7 komşu; O(n log n) |
| Karatsuba | ad + bc = (a + b)(c + d) − ac − bd; 3 çarpım → O(n1,585) |
| Strassen | 7 blok çarpımı → O(n2,807); C22 = P5 + P1 − P3 − P7 |
Özet
Etkileşimli Simülatörler
Özet
Sık Yapılan Hatalar
StackOverflowError. Karatsuba'da x < 10 || y < 10.Özet
Örnek Problemler
- T(n) = 4T(n/2) + n bağıntısını ana teoremle çözün.
- T(n) = 2T(n/2) + n² bağıntısını çözün; düzenlilik koşulunu kontrol edin.
- Karatsuba ile 21 · 43'ü hesaplayın (m = 1).
- A = (0,0), B = (10,0). P = (3,4), Q = (5,−2), R = (7,6) için capraz(A, B, ·) değerlerini bulun. Quickhull üst kümede hangi noktayı seçer?
us(3, 10)kaç çarpım yapar? Saf yöntemle kıyaslayın.- [5, 1, 4, 2, 3] dizisini birleştirerek sıralarken son birleştirmede hangi iki sıralı dizi birleşir?
Cevapları göster
- a = 4, b = 2 → nlog₂4 = n²; f(n) = n daha küçük → durum 1 → Θ(n²).
- nlog₂2 = n; f(n) = n² daha büyük; 2·(n/2)² = n²/2 ≤ ½·n² ✓ → durum 3 → Θ(n²).
- a = 2, b = 1, c = 4, d = 3: z2 = 8, z0 = 3, z1 = 3·7 = 21 → 21 − 8 − 3 = 10 → 800 + 100 + 3 = 903.
- P: 10·4 = 40 (sol), Q: 10·(−2) = −20 (sağ), R: 10·6 = 60 (sol). Üst kümede en büyük capraz → R.
- n: 10 → 5 → 2 → 1 → 0. Çarpımlar: n=1: 2, n=2: 1, n=5: 2, n=10: 1 → 6 (saf: 9). Sonuç 59049.
- orta = 2: [5, 1, 4] → [1, 4, 5] ve [2, 3] → [1, 4, 5] + [2, 3] → [1, 2, 3, 4, 5].
Özet
Alıştırmalar
- Dizinin en büyük elemanını böl ve fethet ile bulun; bağıntıyı çözün.
- Birleştirerek sıralamayı değiştirip ters çiftleri (i < j, a[i] > a[j]) sayın. [2, 4, 1, 3, 5] için sonuç?
- En büyük toplamlı alt dizi: [−2, 1, −3, 4, −1, 2, 1, −5, 4] için böl ve fethet çözümü ve süresi.
- A = [[1, 2], [3, 4]], B = [[5, 6], [7, 8]] çarpımını Strassen ile hesaplayın; C22'yi ± P7 ile deneyin.
- Quickhull için O(n²) süren bir girdi tarif edin.
- En yakın çift algoritmasında taban durumu n ≤ 3 yerine n ≤ 1 olsaydı ne değişirdi?
Cevaplar / ipuçları
- max(sol yarı, sağ yarı); T(n) = 2T(n/2) + O(1) → durum 1 → Θ(n).
- Birleştirmede sağdan eleman alınınca soldaki kalan sayısı eklenir; O(n log n). Sonuç 3.
- max(sol, sağ, ortadan geçen); 2T(n/2) + O(n) = O(n log n). Sonuç 6 ([4, −1, 2, 1]).
- P1..P7 = −2, 24, 35, 8, 65, −30, −22 → C = [[19, 22], [43, 50]]; C22 = 65 − 2 − 35 + 22 = 50 ✓ (+P7 ile 6 ✗).
- Noktalar dışbükey bir eğride ve en uzak nokta hep bir uca komşu (üstel aralıklı): T(n) = T(n − 1) + O(n).
- Tek noktalı yarı ∞ döndürür; sonuç yine doğru (şerit kaçan çifti bulur) ama çağrı sayısı artar.
Özet
Kaynaklar
- Cormen, Leiserson, Rivest ve Stein, Introduction to Algorithms, 4. baskı, 2022 (Bölüm 4: Böl ve fethet; Bölüm 33: Hesaplamalı geometri).
- Kleinberg ve Tardos, Algorithm Design, 2005 (Bölüm 5: Divide and Conquer).
- Sedgewick ve Wayne, Algorithms, 4. baskı, 2011.
- Barber, Dobkin ve Huhdanpaa, "The Quickhull Algorithm for Convex Hulls", ACM TOMS 22(4), 1996.
- Karatsuba ve Ofman, "Multiplication of Multidigit Numbers on Automata", 1962; Strassen, "Gaussian Elimination is not Optimal", Numerische Mathematik 13, 1969.