Bölüm 2: Algoritma Analizi
Giriş
Öğrenme Çıktıları
Bir algoritmayı deneysel olarak ölçmek ve ilkel işlemlerini sayarak çözümlemek.
Zaman ve alan karmaşıklığını O, Ω ve Θ gösterimleriyle ifade etmek.
Döngü kalıplarından en iyi, ortalama ve en kötü durum maliyetini çıkarmak.
Aynı problemi çözen algoritmaları maliyet, doğruluk ve sağlamlık açısından karşılaştırmak.
Algoritmalar ve Ölçüm
Algoritmalar
- Bir algoritma, bir problemi çözmek için adım adım bir prosedürdür: girdi → adımlar → çıktı.
- Aynı problemi çözmek için farklı algoritmalar bulunabilir; bazıları diğerlerine göre daha verimli çalışır.
- Doğru algoritma seçimi kritiktir: iyi bir algoritma, işi daha az kaynak kullanarak yapar.
Bazı yaygın algoritmalar:
Algoritmalar ve Ölçüm
İyi Bir Algoritma
Bir problemi etkili bir şekilde çözen algoritmadır. Dört ölçüte bakarız:
Algoritmalar ve Ölçüm · Ölçerek analiz
Deneysel Analiz: System.nanoTime()
for (int n = 1000; n <= 64000; n *= 2) { int[] a = new int[n]; for (int i = 0; i < n; i++) a[i] = i; // tekrarsız long bas = System.nanoTime(); tekrarVar(a); // ölçülen iş long sure = System.nanoTime() - bas; // ns System.out.println(n + " " + sure / 1e6 + " ms"); }
System.nanoTime() iki okuma arasındaki farkı ns cinsinden verir (duvar saati değil).new int[n] sıfırlarla dolar → tekrarVar (tekrar arayan O(n²) metot) ilk karşılaştırmada true döner. En kötü durumu ölçmek için tekrarsız veri gerekir.Algoritmalar ve Ölçüm · Ölçerek analiz
Katlama Deneyi ve Deneysel Analizin Sınırları
Deneysel analizin sınırları (Goodrich §4.1):
- Sonuçlar donanıma, JVM'e ve yüke bağlıdır; iki algoritma aynı ortamda ölçülmelidir.
- Yalnız sınırlı sayıda girdi denenebilir; önemli bir girdi kaçabilir.
- Ölçmek için algoritmanın tamamen kodlanması gerekir.
Algoritmalar ve Ölçüm · Adım sayma
İlkel İşlemleri Sayma: maksimum()
int maksimum(int[] a) { int enBuyuk = a[0]; for (int i = 1; i < a.length; i++) { if (a[i] > enBuyuk) enBuyuk = a[i]; } return enBuyuk; }
- İlkel işlem: atama, karşılaştırma, aritmetik, dizi indisleme, metot çağrısı / dönüş.
- Her birinin süresi sabit kabul edilir → yalnız kaç kez çalıştıklarını sayarız.
| Satır | İfade | Kaç kez? |
|---|---|---|
| 2 | enBuyuk = a[0] | 1 |
| 3 | i = 1 | 1 |
| 3 | i < a.length | n |
| 4 | a[i] > enBuyuk | n − 1 |
| 5 | enBuyuk = a[i] | 0 … n − 1 |
| 3 | i++ | n − 1 |
| 7 | return | 1 |
Algoritmalar ve Ölçüm · Kodu adım adım çalıştır
Kod İzleme: maksimum(a)
enBuyuk = a[0] = 3: ilk öğe geçici en büyük.
i = 1, 1 < 5 → döngü sürer. Değişmez: enBuyuk = a[0..0]'in en büyüğü.
a[1] = 8 > 3 → doğru.
enBuyuk = 8: yeni en büyük bulundu.
i = 2, 2 < 5 → döngü sürer. Değişmez: enBuyuk = a[0..1]'in en büyüğü.
a[2] = 2 > 8 → yanlış; enBuyuk değişmez.
i = 3, 3 < 5 → döngü sürer. Değişmez: enBuyuk = a[0..2]'in en büyüğü.
a[3] = 9 > 8 → doğru.
enBuyuk = 9: yeni en büyük bulundu.
i = 4, 4 < 5 → döngü sürer. Değişmez: enBuyuk = a[0..3]'in en büyüğü.
a[4] = 4 > 9 → yanlış; enBuyuk değişmez.
i = 5: 5 < 5 yanlış → döngü biter. Tüm dizi işlendi.
return 9. n = 5 için n − 1 = 4 karşılaştırma yapıldı → Θ(n).
int maksimum(int[] a) { int enBuyuk = a[0]; for (int i = 1; i < a.length; i++) { if (a[i] > enBuyuk) enBuyuk = a[i]; } return enBuyuk; }
Asimptotik Gösterim
Zaman Karmaşıklığı ve Büyük O (Big O)
- Algoritmanın ne kadar sürede çalıştığını, girdi boyutu n'ye bağlı olarak ifade eder.
- Büyük O gösterimi, çalışma süresi için bir üst sınır belirtir; genellikle en kötü durum için kullanılır.
- O(1): işlem sayısı girdi boyutuyla büyümez; farklı girdilerde süre birebir aynı olmak zorunda değildir.
- O(n): girdi büyüdükçe süre doğrusal olarak artar.
3n2 + 5n + 2 → O(n2) · 4n + 100 → O(n) · 7 → O(1)
Asimptotik Gösterim
O, Ω ve Θ: Tanım ve Grafik
Büyük O: n ≥ n₀ = 5 için 2n + 10 ≤ 4·n → f(n) = O(n) (c = 4). Küçük n'de (n < 5) f(n) daha büyük; önemli değil.
Büyük Omega: her n ≥ 1 için 2n + 10 ≥ 2·n → f(n) = Ω(n): f, n'den daha yavaş büyümez (alt sınır).
Büyük Teta: n ≥ 5 için 2n ≤ f(n) ≤ 4n → f(n) = Θ(n): iki doğru arasına sıkışır, büyüme hızı tam olarak n.
Asimptotik Gösterim
Asimptotik Sınırlar ve Durumlar
| Analiz | Ne sorar? | Doğrusal arama örneği |
|---|---|---|
| En iyi durum | En elverişli geçerli girdide kaç işlem gerekir? | İlk öğe hedefse Θ(1) |
| Ortalama durum | Bir girdi dağılımı varsayımı altında beklenen maliyet nedir? | Hedefin konumu eşit olasılıklıysa Θ(n) |
| En kötü durum | Her geçerli girdi için garanti edilen üst maliyet nedir? | Hedef yoksa veya sondaysa Θ(n) |
Asimptotik Gösterim · Durum analizi
En İyi, Ortalama ve En Kötü Durum
Dizi [4, 8, 15, 16, 23, 42] üzerinde doğrusal arama; her olası hedef için karşılaştırma sayısı:
- Aynı n için girdiye göre maliyet değişir.
- En kötü durum bir garanti verir ve hesaplaması kolaydır → genellikle bu raporlanır.
- Ortalama bir olasılık dağılımı varsayar (burada her hedef eşit olasılıklı).
- En iyi durum tek başına yanıltıcıdır.
Asimptotik Gösterim
Büyük O Gösterimi Örnekleri
| Gösterim | Adı | Örnek | Neden? |
|---|---|---|---|
| O(1) | Sabit | Dizinin ilk öğesine erişme | Dizinin boyutu ne olursa olsun erişim süresi sabit |
| O(log n) | Logaritmik | Sıralı dizide ikili arama | Her adımda arama alanı yarıya iner |
| O(n) | Doğrusal | Diziyi baştan sona tarama | Her öğe bir kez işlenir |
| O(n log n) | Doğrusal logaritmik | Birleştirme sıralaması (Merge Sort) | Böl ve fethet: log n seviye, her seviyede n iş |
| O(n2) | Kare | Tüm öğe çiftlerini karşılaştırma | İç içe iki döngü |
| O(2n) | Üstel | Tüm alt kümeleri bulma | n öğeli kümenin 2n alt kümesi var |
Asimptotik Gösterim
n Büyüdükçe Ne Olur?
| Karmaşıklık | n = 10 | n = 100 | n = 1.000 |
|---|---|---|---|
| log2 n | 3,3 | 6,6 | 10 |
| n | 10 | 100 | 1.000 |
| n log2 n | 33 | 664 | 9.966 |
| n2 | 100 | 10.000 | 1.000.000 |
| 2n | 1.024 | ≈ 1,3·1030 | ≈ 1,1·10301 |
Koddan Karmaşıklığa · Adım sayma
Döngü Kalıplarından Karmaşıklığa
| Kalıp | Gövde kaç kez? | n = 16 | Sınıf |
|---|---|---|---|
for (i = 0; i < n; i++) | n | 16 | O(n) |
for (i = 0; i < n; i += 2) | n / 2 | 8 | O(n) |
for (i = 1; i < n; i *= 2) | ⌈log₂ n⌉ | 4 | O(log n) |
iç içe: i < n, j < n | n² | 256 | O(n²) |
iç içe: i < n, j < i | n(n−1)/2 | 120 | O(n²) |
ardışık iki i < n döngüsü | 2n | 32 | O(n) |
Koddan Karmaşıklığa · Kodu adım adım çalıştır
Kod İzleme: adimSay(16) — i her turda ikiye katlanır
adimSay(16): kaç kez ikiye katlayarak n'ye ulaşırız?
Sayaç k = 0.
i = 1 < 16 → gövde çalışır.
k++ → k = 1.
i = 2 < 16 → gövde çalışır.
k++ → k = 2.
i = 4 < 16 → gövde çalışır.
k++ → k = 3.
i = 8 < 16 → gövde çalışır.
k++ → k = 4.
i *= 2 → i = 16; 16 < 16 yanlış → döngü biter.
return 4 = log₂ 16. n'yi 1000 kat büyütmek yalnız ~10 tur ekler → O(log n).
int adimSay(int n) { int k = 0; for (int i = 1; i < n; i *= 2) k++; return k; }
Koddan Karmaşıklığa
Koddan Karmaşıklığa
int ilk(int[] a) { return a[0]; }
int toplam(int[] a) { int s = 0; for (int x : a) // n kez s += x; return s; }
boolean tekrarVar(int[] a) { for (int i = 0; i < a.length; i++) for (int j = i + 1; j < a.length; j++) if (a[i] == a[j]) return true; return false; } // dış döngü n, iç döngü ≈ n/2 // → n(n−1)/2 karşılaştırma
Kural: sabitler ve küçük terimler atılır. n(n−1)/2 = n²/2 − n/2 → O(n²)
Koddan Karmaşıklığa · Kodu adım adım çalıştır
Kod İzleme: toplam()
main, toplam(a)'yı çağırır. Yeni bir çağrı çerçevesi açılır.
Metoda girildi; a aynı diziyi gösterir (kopyalanmaz).
Toplam değişkeni s = 0 ile başlar.
Döngü 1. tur: x = a[0] = 7.
s += x → s = 0 + 7 = 7.
Döngü 2. tur: x = a[1] = 2.
s += x → s = 7 + 2 = 9.
Döngü 3. tur: x = a[2] = 9.
s += x → s = 9 + 9 = 18.
Dizide öğe kalmadı; döngüden çıkılır.
return 18: çerçeve kapanır, değer çağırana döner.
println 18 yazar. Döngü gövdesi n = 3 kez çalıştı → O(n).
int toplam(int[] a) { int s = 0; for (int x : a) { s += x; } return s; } // main içinde: System.out.println(toplam(a));
Koddan Karmaşıklığa · Kodu adım adım çalıştır
Kod İzleme: dogrusalArama(a, 23)
Sıralı bir dizide 23 aranıyor; doğrusal arama sıralı olmayı kullanmaz, baştan tek tek bakar.
a[0] = 2 ≠ 23 → i ilerler. Her adımda yalnızca bir öğe elenir.
a[1] = 5 ≠ 23 → i ilerler.
a[2] = 8 ≠ 23 → i ilerler.
a[3] = 12 ≠ 23 → i ilerler.
a[4] = 16 ≠ 23 → i ilerler.
a[5] = 23 == 23 → return 5. 6 karşılaştırma; hedef sonda ya da yoksa n = 10 karşılaştırma → O(n).
int dogrusalArama(int[] a, int hedef) { for (int i = 0; i < a.length; i++) if (a[i] == hedef) return i; return -1; }
Koddan Karmaşıklığa · Kodu adım adım çalıştır
Kod İzleme: ikiliArama(a, 23)
Arama aralığı tüm dizi: lo = 0, hi = 9.
0 ≤ 9 → aralık boş değil, 1. tur başlar.
mid = (0 + 9) / 2 = 4, a[4] = 16.
16 < 23 → hedef sağ yarıda: lo = mid + 1 = 5. Sol yarı elendi.
5 ≤ 9 → aralık boş değil, 2. tur başlar.
mid = (5 + 9) / 2 = 7, a[7] = 56.
56 > 23 → hedef sol yarıda: hi = mid − 1 = 6. Sağ yarı elendi.
5 ≤ 6 → aralık boş değil, 3. tur başlar.
mid = (5 + 6) / 2 = 5, a[5] = 23.
23 == 23 → bulundu, return 5. Yalnızca 3 tur; doğrusal arama 6 karşılaştırma yapardı. Her tur aralığı yarıya indirir → O(log n).
int ikiliArama(int[] a, int hedef) { int lo = 0, hi = a.length - 1; while (lo <= hi) { int mid = (lo + hi) / 2; if (a[mid] == hedef) return mid; if (a[mid] < hedef) lo = mid + 1; else hi = mid - 1; } return -1; }
Koddan Karmaşıklığa · Kodu adım adım çalıştır
Kod İzleme: ikiliArama(a, 40) — hedef yok
Bu kez 40 dizide yok: en kötü durum. Aralık tüm dizi.
0 ≤ 9 → aralık boş değil, 1. tur.
1. tur: mid = (0 + 9) / 2 = 4, a[4] = 16.
16 < 40 → lo = 5; sol taraf elendi.
5 ≤ 9 → aralık boş değil, 2. tur.
2. tur: mid = (5 + 9) / 2 = 7, a[7] = 56.
56 > 40 → hi = 6; sağ taraf elendi.
5 ≤ 6 → aralık boş değil, 3. tur.
3. tur: mid = (5 + 6) / 2 = 5, a[5] = 23.
23 < 40 → lo = 6; sol taraf elendi.
6 ≤ 6 → aralık boş değil, 4. tur.
4. tur: mid = (6 + 6) / 2 = 6, a[6] = 38.
38 < 40 → lo = 7; sol taraf elendi.
7 ≤ 6 yanlış → aralık boş, döngü biter.
return -1. En kötü durumda bile yalnız 4 tur = ⌊log₂ 10⌋ + 1; doğrusal arama 10 karşılaştırma yapardı.
int ikiliArama(int[] a, int hedef) { int lo = 0, hi = a.length - 1; while (lo <= hi) { int mid = (lo + hi) / 2; if (a[mid] == hedef) return mid; if (a[mid] < hedef) lo = mid + 1; else hi = mid - 1; } return -1; }
Koddan Karmaşıklığa · Kodu adım adım çalıştır
Kod İzleme: tekrarVar()
Dış döngü: i = 0 (a[i] = 4). j, i+1'den başlar.
a[0] = 4 ile a[1] = 7 karşılaştırılır → farklı, j ilerler.
a[0] = 4 ile a[2] = 1 karşılaştırılır → farklı, j ilerler.
a[0] = 4 ile a[3] = 7 karşılaştırılır → farklı, j ilerler.
Dış döngü: i = 1 (a[i] = 7). j, i+1'den başlar.
a[1] = 7 ile a[2] = 1 karşılaştırılır → farklı, j ilerler.
a[1] = 7 ve a[3] = 7 eşit → return true. En kötü durumda (tekrar yoksa) n(n−1)/2 = 6 karşılaştırma yapılırdı → O(n²).
boolean tekrarVar(int[] a) { for (int i = 0; i < a.length; i++) for (int j = i + 1; j < a.length; j++) if (a[i] == a[j]) return true; return false; }
Koddan Karmaşıklığa · Aynı problem, iki algoritma
Örnek Problem: Önek Ortalamaları
Girdi x[0..n−1]; çıktı a[j] = (x[0] + … + x[j]) / (j + 1). Kullanım: hareketli ortalama, finansal eğilim analizi (Goodrich §4.3).
a[0] = x[0] … x[0] öğelerinin ortalaması = 4.0.
a[1] = x[0] … x[1] öğelerinin ortalaması = 6.0.
a[2] = x[0] … x[2] öğelerinin ortalaması = 6.0.
a[3] = x[0] … x[3] öğelerinin ortalaması = 5.0.
İki çözüm: her j için baştan topla (O(n²)) · birikimli toplamı taşı (O(n)).
Koddan Karmaşıklığa · Kodu adım adım çalıştır
Kod İzleme: onekOrt1 — her j için baştan topla
n = 4; sonuç dizisi a oluşturulur (0.0 ile dolu).
j = 0: top = 0 — her j için toplam baştan başlar.
top += x[0] = 4 → top = 4.0.
a[0] = 4.0 / 1 = 4.0.
j = 1: top = 0 — her j için toplam baştan başlar.
top += x[0] = 4 → top = 4.0.
top += x[1] = 8 → top = 12.0.
a[1] = 12.0 / 2 = 6.0.
j = 2: top = 0 — her j için toplam baştan başlar.
top += x[0] = 4 → top = 4.0.
top += x[1] = 8 → top = 12.0.
top += x[2] = 6 → top = 18.0.
a[2] = 18.0 / 3 = 6.0.
j = 3: top = 0 — her j için toplam baştan başlar.
top += x[0] = 4 → top = 4.0.
top += x[1] = 8 → top = 12.0.
top += x[2] = 6 → top = 18.0.
top += x[3] = 2 → top = 20.0.
a[3] = 20.0 / 4 = 5.0.
return a. Toplama sayısı 1 + 2 + 3 + 4 = 10 = n(n+1)/2 → O(n²).
double[] onekOrt1(double[] x) { int n = x.length; double[] a = new double[n]; for (int j = 0; j < n; j++) { double top = 0; for (int i = 0; i <= j; i++) top += x[i]; a[j] = top / (j + 1); } return a; }
Koddan Karmaşıklığa · Kodu adım adım çalıştır
Kod İzleme: onekOrt2 — birikimli toplam
top döngüden önce bir kez sıfırlanır ve turlar boyunca korunur.
j = 0: top += x[0] = 4 → top = 4.0 (önceki toplam yeniden kullanıldı).
a[0] = 4.0 / 1 = 4.0.
j = 1: top += x[1] = 8 → top = 12.0 (önceki toplam yeniden kullanıldı).
a[1] = 12.0 / 2 = 6.0.
j = 2: top += x[2] = 6 → top = 18.0 (önceki toplam yeniden kullanıldı).
a[2] = 18.0 / 3 = 6.0.
j = 3: top += x[3] = 2 → top = 20.0 (önceki toplam yeniden kullanıldı).
a[3] = 20.0 / 4 = 5.0.
Aynı sonuç, yalnız 4 toplama (onekOrt1: 10). Tek döngü → O(n).
double[] onekOrt2(double[] x) { int n = x.length; double[] a = new double[n]; double top = 0; for (int j = 0; j < n; j++) { top += x[j]; a[j] = top / (j + 1); } return a; }
Koddan Karmaşıklığa · Aynı problem, iki algoritma
İki Çözümün Karşılaştırması
| n | onekOrt1 | onekOrt2 |
|---|---|---|
| 10 | 55 | 10 |
| 100 | 5.050 | 100 |
| 1.000 | 500.500 | 1.000 |
| 1.000.000 | 500.000.500.000 | 1.000.000 |
Alan ve Doğruluk
Alan Karmaşıklığı
- Algoritmanın kullandığı bellek miktarını ölçer; genellikle Büyük O gösterimiyle ifade edilir.
- Bellek kullanımının girdi boyutuna bağlı artışını gösterir (girdinin kendisi çoğu zaman sayılmaz; ek alan).
- Sınırlı bellek kaynaklarına sahip sistemlerde bellek verimliliği önemlidir.
Alan ve Doğruluk
Doğruluk (Correctness)
- Doğru bir algoritma, her geçerli girdi için sonlu sürede beklenen çıktıyı üretir.
- Hızlı çalışan ama yanlış sonuç veren bir algoritmanın değeri yoktur.
Doğruluk nasıl gösterilir?
Alan ve Doğruluk
Sağlamlık (Robustness)
- Algoritmanın beklenmeyen durumlarla başa çıkma yeteneğidir.
- Sağlam bir algoritma, normal aralığın dışındaki girdileri bile çökmeden veya yanlış sonuç üretmeden işleyebilir.
Sağlamlık nasıl sınanır?
Özet
Sık Yapılan Hatalar
j *= 2 ile ilerliyorsa n log n; sabit sayıda dönüyorsa O(n).(lo + hi) / 2 taşmasıÇok büyük dizilerde int taşar; lo + (hi - lo) / 2 güvenlidir.a == b ile dizi karşılaştırmak== referansları karşılaştırır; içerik için Arrays.equals(a, b).Özet
Özet
| Konu | Hatırlanacaklar |
|---|---|
| Deneysel analiz | süre donanıma ve girdiye bağlıdır; katlama deneyi: T(2n)/T(n) ≈ 2k → T(n) ≈ c·nk |
| İlkel işlem sayma | atama, karşılaştırma, aritmetik, dizi erişimi; donanımdan bağımsız, tüm girdiler için |
| O, Ω, Θ | üst, alt ve sıkı sınır; sabit çarpanlar ve küçük terimler atılır |
| Durumlar | en iyi, ortalama, en kötü; garanti için en kötü durum, uzun işlem dizisi için amortize |
| Döngü kalıpları | tek döngü O(n) · iç içe O(n²) · yarıya inen O(log n) · dış n, iç log n → O(n log n) |
| Algoritma seçimi | önek ortalamaları O(n²) → O(n); sıralı dizide ikili arama O(log n) |
| Alan, doğruluk | ek bellek de Büyük O ile ölçülür; doğru ve sağlam olmayan hızlı algoritmanın değeri yoktur |
Özet
Temel Veri Yapılarında İşlem Maliyetleri
| Veri yapısı | i. öğeye erişim | Arama | Ekleme | Silme |
|---|---|---|---|---|
| Dizi | O(1) | O(n) | O(n) | O(n) |
| Bağlı liste | O(n) | O(n) | O(1)† | O(1)† |
| Yığın | yalnızca üst | O(n) | O(1) push | O(1) pop |
| Kuyruk | yalnızca ön | O(n) | O(1) enqueue | O(1) dequeue |
| Eşleme / Küme (hash) | — | O(1)* | O(1)* | O(1)* |
† Konum (önceki düğüm) biliniyorsa. * Ortalama durum; en kötü durumda O(n).
Özet
Örnek Problemler
- Tüm öğe çiftlerini karşılaştıran algoritmanın zaman karmaşıklığı nedir?
- f(n) = 5n³ + 2n² + 100 hangi Θ sınıfındadır?
- n = 1024 öğeli sıralı dizide ikili arama en kötü durumda kaç tur döner?
for (int i = 1; i < n; i *= 2)döngüsü kaç kez döner?- Doğrusal aramanın en iyi ve en kötü durumu nedir?
- A algoritması 100n, B algoritması n² adım atıyor. Hangi n değerleri için A daha hızlıdır?
Cevapları göster
- n(n − 1)/2 karşılaştırma → O(n2).
- Θ(n³): en hızlı büyüyen terim belirler, sabitler atılır.
- ⌊log₂ 1024⌋ + 1 = 11 tur.
- i = 1, 2, 4, …: ⌈log₂ n⌉ tur → O(log n).
- En iyi: hedef ilk öğe, Θ(1). En kötü: hedef sonda ya da yok, Θ(n).
- 100n < n² ⇔ n > 100: büyük n için daha yavaş büyüyen algoritma kazanır.
Özet
Alıştırmalar
- Kod parçasının Büyük O'su nedir?
for (int i = n; i > 1; i /= 2) for (int j = 0; j < n; j++) s++;
- f(n) = 3n² + 5n + 2 = O(n²) olduğunu c ve n₀ vererek gösterin.
- Katlama deneyinde n iki katına çıkınca süre ≈ 8 katına çıkıyor. T(n) hangi sınıfta?
- n = 5 için onekOrt1 ve onekOrt2 kaçar toplama yapar?
for (i = 0; i < n; i++) for (j = i; j < n; j++) s++;sonunda s kaçtır?- O(n²) bir algoritma n = 1000 için 2 saniye sürüyor. n = 4000 için süre yaklaşık kaçtır?
Cevaplar / ipuçları
- Dış döngü ⌊log₂ n⌋ tur, iç döngü n → O(n log n).
- n ≥ 1 için 5n ≤ 5n² ve 2 ≤ 2n² → f(n) ≤ 10n²: c = 10, n₀ = 1.
- 2³ = 8 → O(n³) (kübik).
- onekOrt1: 1+2+3+4+5 = 15; onekOrt2: 5.
- n + (n − 1) + … + 1 = n(n + 1)/2 → O(n²).
- n 4 katına çıkınca süre 4² = 16 katına: ≈ 32 saniye.
Özet
Kaynaklar
- Goodrich, Tamassia ve Goldwasser, Data Structures and Algorithms in Java, 6. baskı, 2014.
- Cormen, Leiserson, Rivest ve Stein, Introduction to Algorithms, 4. baskı, 2022.
- Sedgewick ve Wayne, Algorithms, 4. baskı, 2011.