Bölüm 6: 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; ana teoremle (master theorem) böl ve fethet algoritmalarının süresini bulmak.
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). Ş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.
- 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ştirme sıralamasında 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 · Kodu adım adım çalıştır
Şablonun Uygulaması: En Büyük Öğe
int enBuyuk(int[] a, int alt, int ust) { if (alt == ust) return a[alt]; // taban int orta = (alt + ust) / 2; int sol = enBuyuk(a, alt, orta); int sag = enBuyuk(a, orta + 1, ust); return Math.max(sol, sag); // birleştir }
Dizi [5, 2, 9, 4, 7]; enBuyuk(a, 0, 4) çağrıldı. Aralıkta birden çok öğe var → orta = 2, önce sol yarı [0..2] çözülür.
enBuyuk(0, 2): orta = 1 → önce sol yarı [0..1], sonra sağ yarı [2..2].
enBuyuk(0, 1): orta = 0 → önce sol yarı [0..0], sonra sağ yarı [1..1].
enBuyuk(0, 0): tek öğe → taban durumu, a[0] = 5 döner.
enBuyuk(1, 1): tek öğe → taban durumu, a[1] = 2 döner.
enBuyuk(0, 1): sol = 5, sağ = 2 → birleştir: max = 5 döner.
enBuyuk(2, 2): tek öğe → taban durumu, a[2] = 9 döner.
enBuyuk(0, 2): sol = 5, sağ = 9 → birleştir: max = 9 döner.
enBuyuk(3, 4): orta = 3 → önce sol yarı [3..3], sonra sağ yarı [4..4].
enBuyuk(3, 3): tek öğe → taban durumu, a[3] = 4 döner.
enBuyuk(4, 4): tek öğe → taban durumu, a[4] = 7 döner.
enBuyuk(3, 4): sol = 4, sağ = 7 → birleştir: max = 7 döner.
enBuyuk(0, 4): sol = 9, sağ = 7 → birleştir: max = 9 döner. Sonuç 9: n yaprak, n − 1 karşılaştırma; T(n) = 2T(n/2) + O(1) = O(n).
Paradigma
Klasik Böl ve Fethet Algoritmaları
| Algoritma | Böl | Birleştir | Bağıntı | Süre |
|---|---|---|---|---|
| İkili arama | ortadaki öğeye bak, bir yarıyı at | yok | T(n/2) + O(1) | O(log n) |
| Birleştirme sıralaması | 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ı
Ana Teorem ve Bölümün Algoritmaları
T(n) = a·T(n/b) + f(n), a ≥ 1, b > 1. f(n), yaprakların toplam işi nlogb a ile karşılaştırılır: f(n) polinom olarak küçükse Θ(nlogb a) (durum 1, yapraklar baskın), aynı mertebedeyse Θ(nlogb a · log n) (durum 2), polinom olarak büyükse ve düzenlilik koşulu sağlanıyorsa Θ(f(n)) (durum 3, kök baskın).
| Algoritma | a | b | f(n) | nlogb a | Durum | T(n) |
|---|---|---|---|---|---|---|
| İkili arama (azalt ve fethet), hızlı üs alma | 1 | 2 | 1 | n⁰ = 1 | 2 | Θ(log n) |
| Birleştirme sıralaması, en yakın çift, dengeli hızlı sıralama | 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) |
Karatsuba ve Strassen'in tüm kazancı a'yı bir azaltmaktan gelir: 4 → 3 ve 8 → 7. Quickhull (T(n₁) + T(n₂) + n) ve dengesiz hızlı sıralama (T(n − 1) + n) eşit olmayan bölmeler olduğundan ana teoreme uymaz; bunlar özyineleme ağacıyla çözülür.
Temel Örnekler
Birleştirme Sıralaması: Böl ve Fethet Bakışı
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 öğeli 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.
- Böl: diziyi ortadan ikiye ayır, O(1). Yönet: iki yarıyı özyinelemeli sırala. Birleştir: sıralı yarıları tek geçişte birleştir, Θ(n).
- T(n) = 2T(n/2) + Θ(n) → durum 2 → Θ(n log n); en iyi, ortalama ve en kötü durumda aynı. Asıl iş birleştirmede yapılır.
Temel Örnekler
Hızlı Sıralama: Böl ve Fethet Bakışı
Böl: pivota göre parçala, Θ(n). Yönet: iki parçayı özyinelemeli sırala. Birleştir: yok; parçalar yerinde sıralanır. Asıl iş bölmede yapılır.
Dizi [10 80 30 90 40 50 70]; Lomuto parçalaması: son öğe 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ş parçalamada 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). n = 1000'de 999'a karşı 16, n = 10⁶'da 999.999'a karşı 27 çarpım. y tek kez hesaplanır; us(x, n / 2) * us(x, n / 2) yazmak T(n) = 2T(n/2) + O(1) = Θ(n) verir.
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, 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.
- Noktalara çivi çakılıp etraflarına bir lastik bant geçirildiğinde 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, parçalama üç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 parçalama): 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)
Problem: düzlemdeki n nokta arasından Öklid uzaklığı d(p, q) = √((pₓ − qₓ)² + (py − qy)²) en küçük olan çifti bulmak.
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).
Ö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ştirme sıralaması 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ştirme sıralamasıyla 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 öğesini böl ve fethet ile bulun; bağıntıyı çözün.
- Birleştirme sıralamasını 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 öğe 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.