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.
Yineleme 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 problem daha küçük, yönetilebilir alt problemlere bölünür.
- Parçala: alt problemler, doğrudan çözülebilecek kadar küçülene dek bölünmeye devam eder (özyineleme).
- Yönet: her alt problem ayrı ayrı çözülür.
- Birleştir: alt problemlerin çözümleri birleştirilerek asıl çözüm kurulur.
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) |
Yineleme 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: dizi ortadan ikiye ayrılır, O(1). Yönet: iki yarı özyinelemeli sıralanır. Birleştir: sıralı yarılar tek geçişte birleştirilir, Θ(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 bölümlenir, Θ(n). Yönet: iki parça özyinelemeli sıralanır. 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 bölümlemesi: 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ş 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, bu yöntem 7 çarpım; n = 10⁶'da 999.999'a karşı 27 → 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 saklanır → 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 bulunur; ikisi de örtüdedir.
- AB doğrusu noktaları iki alt kümeye ayırır: doğrunun üstü (solu) ve altı (sağı).
- Bir alt kümede AB'ye en uzak C noktası bulunur; C örtüdedir.
- ACB üçgeninin içindeki noktalar elenir: örtüde olamazlar.
- AC'nin ve CB'nin dışında kalanlar için özyineleme yapılır.
- Hiç nokta kalmayınca durulur; 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)
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ıralanır.
- 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ılır.
- Şerit y sırasıyla taranır; 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ünür: 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 taban çarpımı (okul yöntemi 16 tek basamaklı çarpım).
- 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 ve C, n/2 × n/2'lik dört bloğa bölünür:
| 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 karşılaştırı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.