O(n log n) ile medyan bulma
- Bir listeyi sıraladıktan sonra medyanı seçmek en basit yöntemdir
- Karşılaştırma tabanlı sıralamanın zaman karmaşıklığı
O(n log n)'dir - Kod örneği:
def nlogn_median(l): l = sorted(l) if len(l) % 2 == 1: return l[len(l) // 2] else: return 0.5 * (l[len(l) // 2 - 1] + l[len(l) // 2])
Ortalama O(n) ile medyan bulma
-
Medyan, "quickselect" algoritması kullanılarak ortalama olarak doğrusal zamanda bulunabilir
-
Tony Hoare tarafından geliştirilen özyinelemeli bir algoritmadır
-
Süreç:
- Listeden rastgele bir indeks seçilip pivot olarak belirlenir
- Liste, pivot temel alınarak iki gruba ayrılır:
- pivottan küçük veya pivota eşit öğeler
- pivottan büyük öğeler
- Medyanı içeren grup özyinelemeli olarak aranır
-
Kod örneği:
import random def quickselect_median(l, pivot_fn=random.choice): if len(l) % 2 == 1: return quickselect(l, len(l) // 2, pivot_fn) else: return 0.5 * (quickselect(l, len(l) // 2 - 1, pivot_fn) + quickselect(l, len(l) // 2, pivot_fn)) def quickselect(l, k, pivot_fn): if len(l) == 1: assert k == 0 return l[0] pivot = pivot_fn(l) lows = [el for el in l if el < pivot] highs = [el for el in l if el > pivot] pivots = [el for el in l if el == pivot] if k < len(lows): return quickselect(lows, k, pivot_fn) elif k < len(lows) + len(pivots): return pivots[0] else: return quickselect(highs, k - len(lows) - len(pivots), pivot_fn)
Ortalama O(n) kanıtı
- Pivot listenin yaklaşık yarıya bölünmesini sağladığında, her özyinelemeli çağrı bir önceki adımın verisinin yarısı üzerinde çalışır
- Matematiksel kanıt:
C = n + n/2 + n/4 + n/8 + ... = 2n = O(n)
Deterministik O(n)
-
En kötü durumda bile doğrusal zamanı garanti eder
-
Pivot seçmek için "median-of-medians" algoritması kullanılır
-
Süreç:
- Liste 5'li gruplara ayrılır
- Her grup sıralanır ve medyan seçilir
- Medyanların medyanı pivot olarak seçilir
-
Kod örneği:
def pick_pivot(l): assert len(l) > 0 if len(l) < 5: return nlogn_median(l) chunks = chunked(l, 5) full_chunks = [chunk for chunk in chunks if len(chunk) == 5] sorted_groups = [sorted(chunk) for chunk in full_chunks] medians = [chunk[2] for chunk in sorted_groups] median_of_medians = quickselect_median(medians, pick_pivot) return median_of_medians def chunked(l, chunk_size): return [l[i:i + chunk_size] for i in range(0, len(l), chunk_size)]
Özet
- quickselect algoritması, uygun bir pivot seçildiğinde medyanı doğrusal zamanda bulabilir
- median-of-medians algoritması, en kötü durumda bile doğrusal zamanı garanti eden bir pivot seçme yöntemidir
- Pratikte rastgele pivot seçimi yeterince etkilidir
GN⁺ özeti
- Bu yazı, medyan bulmaya yönelik çeşitli algoritmaları açıklar ve özellikle medyanı doğrusal zamanda bulma yöntemini ele alır
- quickselect algoritması ortalamada hızlıdır, ancak en kötü durum için median-of-medians algoritması kullanılabilir
- Gerçek uygulamalarda rastgele pivot seçimi çoğu zaman yeterince etkilidir
- Benzer işleve sahip bir algoritma olan introselect de vardır; bu algoritma C++ standart kütüphanesinde kullanılır
1 yorum
Hacker News görüşleri