Aşağıdakine göre daha yüksek big-O zaman karmaşıklığı algoritmasını tercih edeceğiniz durumlar var mı?


242

O(log n)Zaman karmaşıklığını zaman karmaşıklığına tercih edeceğiniz durumlar var O(1)mı? Ya da O(n)hiç O(log n)?

Hiç örneğin var mı?


67
O(log n)O(1)
Birini

14
Teorik bilgisayar bilimlerinden O (1) operasyonları ile tonlarca pratik olmayan veri yapısı vardır. Bir örnek, 5 dolaylı aktarım katmanı kullanılarak, işlem başına o (n) ekstra alan ve O (1) olarak desteklenebilen bitvektörlerde select () olacaktır. O kombine Basit ikili arama (1) rank () yazarına göre pratikte daha hızlı olarak çıkıyor Özlü Veri Yapısı Kütüphane
Niklas B 'ye

17
Düşük asimtotik karmaşıklık, daha hızlı çalışma sürelerini garanti etmez. Somut bir örnek için araştırma matrisi çarpımı.
Connor Clark

54
Ayrıca ... herhangi bir algoritma yeterince büyük bir tablo araması göz önüne alındığında O (1) 'e dönüştürülebilir;)
Connor Clark

19
@Hoten - Bu, masa aramasının O (1) olduğunu varsayarsak, bahsettiğiniz tabloların boyutu için hiç verilmez! :)
Jander

Yanıtlar:


267

Düşük olana göre daha yüksek büyük O zaman karmaşıklığına sahip bir algoritmayı tercih etmek için birçok neden olabilir:

  • çoğu zaman, düşük big-O karmaşıklığının elde edilmesi daha zordur ve yetenekli uygulama, çok fazla bilgi ve çok fazla test gerektirir.
  • big-O, bir sabit hakkındaki ayrıntıları gizler : performans gösteren algoritma, 10^5büyük-O bakış açısından 1/10^5 * log(n)( O(1)vs O(log(n)) ' den daha iyidir , ancak en mantıklı nolarak ilk olan daha iyi performans gösterecektir. Örneğin, matris çarpımı için en iyi karmaşıklık, O(n^2.373)ancak sabit o kadar yüksektir ki (benim bildiğim kadarıyla) hiçbir hesaplama kütüphanesi bunu kullanmaz.
  • big-O büyük bir şeyi hesapladığınızda mantıklıdır. Eğer üç sayı dizisini sıralamak gerekirse, gerçekten ufak kullanmak ister konularda O(n*log(n))veya O(n^2)algoritması.
  • bazen küçük harf karmaşıklığının avantajı gerçekten ihmal edilebilir. Örneğin ,O(log log N) bir öğeyi bulmak için zaman karmaşıklığı veren bir veri yapısı tango ağacı vardır , ancak aynı şeyi bulan bir ikili ağaç da vardır O(log n). Çok sayıda n = 10^20fark olsa bile ihmal edilebilir.
  • zaman karmaşıklığı her şey değildir. Çalışan O(n^2)ve O(n^2)bellek gerektiren bir algoritma düşünün . N gerçekten büyük olmadığında O(n^3)zaman ve O(1)mekanda tercih edilebilir . Sorun, uzun süre beklemeniz, ancak algoritmanızla kullanmak için yeterince büyük bir RAM bulabileceğinizden şüphe duymanızdır.
  • paralelleştirme dağıtık dünyamızda iyi bir özellik. Kolayca paralelleştirilebilen algoritmalar vardır ve hiç paralelleştirilemeyen algoritmalar vardır. Bazen, daha iyi bir karmaşıklığa sahip bir makineyi kullanmaktan daha yüksek karmaşıklığa sahip 1000 emtia makinesinde bir algoritma çalıştırmak mantıklıdır.
  • bazı yerlerde (güvenlik) karmaşıklık bir gereklilik olabilir. Hiç kimse hızlı bir şekilde hash yapabilen bir karma algoritmaya sahip olmak istemez (çünkü o zaman diğer insanlar sizi daha hızlı bruteforce edebilir)
  • ancak bu durum karmaşıklığın değişmesi ile ilgili olmasa da, güvenlik işlevlerinden bazıları zamanlama saldırısını önleyecek şekilde yazılmalıdır . Çoğunlukla aynı karmaşıklık sınıfında kalırlar, ancak bir şey yapmak her zaman daha kötü durumda olacak şekilde değiştirilirler. Bir örnek, dizelerin eşit olduğunu karşılaştırmaktır. Çoğu uygulamada, ilk baytlar farklıysa hızlı kırmak mantıklıdır, ancak güvenlikte yine de kötü haberi söylemek için sonuna kadar bekleyeceksiniz.
  • Birisi düşük karmaşıklık algoritmasını patentledi ve bir şirketin para ödemekten daha yüksek karmaşıklık kullanması daha ekonomik.
  • bazı algoritmalar belirli durumlara iyi uyum sağlar. Ekleme sıralaması, örneğin, O(n^2)hızlı sıralama veya birleştirme sıralamasından daha kötü bir ortalama zaman karmaşıklığına sahiptir , ancak çevrimiçi bir algoritma olarak, diğer çoğu algoritmanın yalnızca verimli bir şekilde çalışabildiği bir değer listesini alındıklarında (kullanıcı girişi olarak) verimli bir şekilde sıralayabilir değerlerin tam listesi.

6
Ayrıca, birkaç kez insanların merkezi algoritmalarının büyük O'suna odaklandığını, ancak kurulum maliyetlerini göz ardı ettiğini gördüm. Örneğin, bir karma tablo oluşturmak, bir diziyi tekrar tekrar yapmanız gerekmiyorsa doğrusal olarak bir diziden geçmekten daha pahalı olabilir. Aslında, modern CPU'ların oluşturulma şekli nedeniyle, ikili arama gibi bir şey bile, sıralı dizilerde doğrusal bir arama kadar hızlı olabilir - profil oluşturma bir zorunluluktur.
Luaan

@Luaan "Aslında, modern CPU'ların oluşturulma şekli nedeniyle, ikili arama gibi bir şey bile sıralı dizilerde doğrusal bir arama kadar hızlı olabilir - profil oluşturma bir zorunluluktur." İlginç! Modern bir CPU'da ikili arama ve doğrusal aramanın nasıl aynı zaman alabileceğini açıklayabilir misiniz?
DJG


2
@DenisdeBernardy: Hayır, aslında değil. P'de algoritmalar olabilirler. Ve bunlar, paralelleştirmenin ne anlama geldiğinin makul tanımları olmasa bile, P! = NP anlamına gelmez. Ayrıca, deterministik olmayan bir tur makinesinin olası çalışmalarının aramasının oldukça paralelleştirilebileceğini unutmayın.
einpoklum

228

Her zaman O (log n ) algoritmasında daha düşük olabilecek gizli sabit vardır . Böylece gerçek hayattaki veriler için pratikte daha hızlı çalışabilir.

Alan endişeleri de var (örneğin bir ekmek kızartma makinesinde koşma).

Ayrıca geliştirici zaman kaygısı da vardır - O (log n ) uygulaması ve doğrulaması 1000 × daha kolay olabilir.


Güzel, teşekkürler. Program kararlılığını sağlamak için bir O (logn) algoritması da düşünmeye değer olabileceğini düşünüyordum (örneğin, kendini dengeleyen ikili ağaçlarda)
V.Leymarie

16
Düşünebileceğim bir örnek: küçük bir sıralama dizisi için, programcı için tam bir karma harita uygulaması yazmak ve bunun yerine kullanmak yerine ikili bir arama işlevi uygulamak daha kolay ve daha kompakt olurdu.
Albay Otuz İki

5
Karmaşıklığa bir örnek: sıralanmamış bir listenin medyanını bulmak O (n * log n) 'de yapmak kolaydır, ancak O (n)' de yapmak zordur.
Paul Draper

1
-1, ekmek kızartma makinenize günlükleri koymayın ... Şaka bir yana, bu nokta. lg nböylece, bu yüzden, bu kadar yakın olan kbüyük için nen operasyonlar fark asla.
corsiKa

3
Çoğu insanın aşina olduğu algoritmik karmaşıklıkların önbellek etkilerini dikkate almadığı gerçeği de vardır. İkili ağaçta bir şey aramak, çoğu insana göre O (log2 (n)) 'dir, ancak gerçekte çok daha kötüdür, çünkü ikili ağaçların konumu kötüdür.
Doval

57

Henüz kimsenin hafızaya bağlı uygulamalardan bahsetmediğine şaşırdım.

Karmaşıklığı nedeniyle (yani O (1) < O (log n )) veya karmaşıklığın önündeki sabit daha küçük olduğu için (yani 2 n 2 <6 n 2 ) daha az kayan nokta işlemine sahip bir algoritma olabilir. . Ne olursa olsun, daha düşük FLOP algoritması daha fazla belleğe bağlıysa, daha fazla FLOP içeren algoritmayı tercih edebilirsiniz.

"Belleğe bağlı" ile kastettiğim, sürekli önbellek dışında kalan verilere eriştiğinizdir. Bu verileri almak için işleminizi gerçekleştirmeden önce belleği gerçekte bellek alanınızdan önbelleğinize almanız gerekir. Bu getirme adımı genellikle oldukça yavaştır - işleminizin kendisinden çok daha yavaştır.

Bu nedenle, algoritmanız daha fazla işlem gerektiriyorsa (yine de bu işlemler zaten önbellekte olan verilerde gerçekleştirilir (ve bu nedenle getirme gerekmez)), algoritmanız daha az işlemle (dışarıda yapılması gereken) - gerçek duvar zamanı açısından önbellek verilerini [ve dolayısıyla getirmeyi gerektirir]).


1
Alistra, "uzay endişeleri" hakkında konuşurken dolaylı olarak bunu ele aldı
Zach Saucier

2
Büyük miktarda önbellek özlüyor sadece son yürütme sabit bir değer ile çarpar (1.6GHz ram ile 4 çekirdekli 3.2GHz CPU için 8'den büyük değildir, genellikle çok daha düşüktür), bu yüzden büyük bir sabit sabit olarak sayılır -O gösterim. Dolayısıyla önbelleğin kaçırdığı tek şey, n (0) eşiğini O (n) çözeltisinin O (1) çözeltisinden daha yavaş olmaya başladığı yerde hareket ettirmektir.
Marian Spanik

1
@MarianSpanik Elbette haklısınız. Ama bu soru tercih ediyorum bir durum istedi O(logn)üzerinde O(1). Mümkün olan her şey için n, daha az bellek gerektiren uygulamanın daha yüksek karmaşıklıkta bile daha hızlı duvar zamanında çalışacağı bir durumu kolayca hayal edebilirsiniz .
NoseKnowsAll

@MarianSpanik, 300 saat döngüsüne kadar önbellek kaçırmıyor mu? 8 nereden geliyor?
HopefullyHelpful

43

Veri güvenliğinin önemli olduğu bağlamlarda, daha karmaşık algoritmanın zamanlama saldırılarına karşı daha iyi direnci varsa, daha az karmaşık bir algoritmaya daha karmaşık bir algoritma tercih edilebilir .


6
Söyledikleriniz doğru olsa da, bu durumda O (1) 'de yürütülen bir algoritma tanım gereği zamanlama saldırılarına karşı savunmasızdır.
Justin Lessard

17
@ JustinLessard: O (1) olmak, algoritmanın çalışma zamanının bir sabitle sınırlandırılmasından sonra bazı girdi boyutlarının olduğu anlamına gelir. Bu eşiğin altında ne olduğu bilinmiyor. Ayrıca, algoritmanın herhangi bir gerçek dünya kullanımı için eşik bile karşılanmayabilir. Algoritma doğrusal olabilir ve bu nedenle örneğin girişin uzunluğu hakkında bilgi sızdırır.
Jörg W Mittag

12
Çalışma zamanı, yine de sınırlandırılırken farklı şekillerde dalgalanabilir. Çalışma zamanı orantılıysa (n mod 5) + 1, yine de O(1)hakkında bilgi verir n. Bu nedenle, asemptotik (ve muhtemelen pratikte) daha yavaş olsa bile daha sorunsuz çalışma süresine sahip daha karmaşık bir algoritma tercih edilebilir.
Christian Semrau

Temelde bcrypt'in iyi kabul edilmesinin nedeni budur; işleri yavaşlatır
David, Reinstate Monica

@DavidGrinberg bcrypt'in kullanılmasının nedeni budur ve soruya uyar. Ancak bu, zamanlama saldırıları hakkında konuşan bu cevapla ilgisizdir.
Christian Semrau

37

Alistra çivilenmiş ama örnek veremedi, ben yapacağım.

Mağazanızın sattığı ürün için 10.000 UPC kodu içeren bir listeniz var. 10 haneli UPC, fiyat için tam sayı (pennies cinsinden fiyat) ve makbuz için 30 karakter açıklaması.

O (log N) yaklaşımı: Sıralanmış bir listeniz var. ASCII ise 44 bayt, Unicode ise 84 bayt. Alternatif olarak, UPC'ye int64 gibi davranın ve 42 ve 72 bayt elde edin. 10.000 kayıt - en yüksek durumda, bir megabaytlık depolama alanının biraz altına bakıyorsunuz.

O (1) yaklaşımı: UPC'yi saklamayın, bunun yerine diziye giriş olarak kullanın. En düşük durumda terabaytlık bir depolama alanının neredeyse üçte birine bakıyorsunuz.

Hangi yaklaşımı kullandığınız, donanımınıza bağlıdır. Çoğu makul modern konfigürasyonda log N yaklaşımını kullanacaksınız. RAM'in kritik derecede kısa olduğu ancak bol miktarda yığın depolama alanınız olan bir ortamda çalışıyorsanız, ikinci yaklaşımın doğru cevap olduğunu düşünebilirim. Bir diskteki terabaytın üçte biri önemli değildir, verilerinizi diskin bir sondasına almak bir şeye değer. Basit ikili yaklaşım ortalama 13 alır. (Ancak, anahtarlarınızı kümeleyerek bunu garantili 3 okumaya indirebileceğiniz ve pratikte ilkini önbelleğe alabileceğinizi unutmayın.)


2
Burada biraz kafam karıştı. 10 milyar girişlik bir dizi oluşturmak (çoğu tanımsız olacak) ve UPC'yi bu diziye bir dizin olarak ele almaktan mı bahsediyorsunuz?
David Z

7
@DavidZ Evet. Seyrek bir dizi kullanırsanız, O (1) alamayabilirsiniz, ancak yalnızca 1MB bellek kullanır. Gerçek bir dizi kullanırsanız, O (1) erişiminiz olur ancak 1/3 TB bellek kullanır.
Navin

Modern bir sistemde, 1/3 TB adres alanı kullanacaktır, ancak bu, tahsis edilen bu destek belleğine yakın bir yere geleceği anlamına gelmez. Çoğu modern işletim sistemi, ihtiyaç duyulana kadar tahsisler için depolama işlemi yapmaz. Bunu yaparken, esas olarak OS / donanım sanal bellek sistemindeki verileriniz için ilişkilendirilebilir bir arama yapısı gizlersiniz.
Phil Miller

@Novelocrat True, ancak RAM hızlarında yapıyorsanız, arama süresi önemli değil, 1mb yerine 40mb kullanmak için bir neden yok. Dizi sürümü yalnızca depolama erişimi pahalı olduğunda mantıklıdır - diske gidiyorsunuz.
Loren Pechtel

1
Ya da bu, performans açısından kritik bir işlem olmadığında ve geliştirici zamanı pahalı olduğunda - malloc(search_space_size)geri döndüğünü söylemek ve abone olmak, elde etmek kadar kolaydır.
Phil Miller

36

Kırmızı-siyah bir ağaç düşünün. Erişebilir, arayabilir, ekleyebilir ve silebilirO(log n) . Erişimi olan bir dizi ile karşılaştırın O(1)ve işlemlerin geri kalanı O(n).

Bu nedenle, eriştiğimizden daha sık eklediğimiz, sildiğimiz veya aradığımız bir uygulama ve sadece bu iki yapı arasında bir seçim yapıldığında, kırmızı-siyah ağacı tercih ederiz. Bu durumda, kırmızı-siyah ağacın daha hantal O(log n)erişim süresini tercih ettiğimizi söyleyebilirsiniz .

Neden? Çünkü erişim bizim en büyük endişemiz değil. Bir takas yapıyoruz: başvurumuzun performansı, bunun dışındaki faktörlerden daha fazla etkileniyor. Diğer algoritmaları optimize ederek büyük kazançlar elde ettiğimiz için bu özel algoritmanın performanstan etkilenmesine izin veriyoruz.

Sorunuzun cevabı basitçe şu: algoritmanın büyüme oranı optimize etmek istediğimiz şey olmadığında, optimize etmek istediğimizde şey olmadığında, başka bir şeyi. Diğer tüm cevaplar bunun özel durumlarıdır. Bazen diğer işlemlerin çalışma süresini optimize ederiz. Bazen bellek için optimize ediyoruz. Bazen güvenlik için optimize ediyoruz. Bazen sürdürülebilirliği optimize ederiz. Bazen geliştirme süresi için optimize ederiz. Algoritmanın büyüme hızının çalışma süresi üzerinde en büyük etki olmadığını bildiğinizde, önemli olan sabitin önemli ölçüde düşük olması bile çalışma süresi için optimize eder. (Veri kümeniz bu aralığın dışındaysa, algoritmanın büyüme oranını optimize edersiniz, çünkü sonunda sabite hükmeder.) Her şeyin bir maliyeti vardır ve birçok durumda, daha yüksek bir büyüme oranının maliyetini başka bir şey optimize etmek için algoritma.


O (1) arama ve güncellemeler O (n) ile dizi kullanmanıza izin veren işlemlerin kırmızı-siyah ağaca, insanların düşünmeye alışık olduğundan emin değilim (en azından ben). Çoğu zaman ilk olarak kırmızı-siyah ağaç için anahtar tabanlı arama hakkında düşünürdüm. Ancak dizi ile eşleştirmek için, ekleme sırasında dizin tabanlı arama ve yeniden dizin sağlamak için alt düğümlerin miktarını üst düğümlerde tutan biraz farklı bir yapı olmalıdır. Kırmızı-siyahın dengeyi korumak için kullanılabileceğini kabul etsem de, ilgili işlemlerin detayları hakkında belirsiz olmak istiyorsanız dengeli ağacı kullanabilirsiniz.
ony

@ony Bir harita / sözlük türü yapıyı tanımlamak için kırmızı-siyah bir ağaç kullanılabilir, ancak olması gerekmez. Düğümler sadece temelde sıralı bir liste uygulayan elemanlar olabilir.
jpmc26

öğelerin sırasını tanımlayan sıralı liste ve dizi farklı miktarda bilgiye sahiptir. Biri, elemanlar ve kümeler arasındaki düzene dayanır ve diğeri, elemanlar arasındaki düzeni tanımlayan keyfi diziyi tanımlar. Başka bir şey, O(log n)"kırmızı-siyah ağaç" olduğunu beyan ettiğiniz "erişim" ve "arama " nedir? Arasında yerleştirin 5dizinin 2 konumunda [1, 2, 1, 4]neden olur[1, 2, 5, 1 4] (element 4indeksi 4'e 3 ila güncellenecektir). O(log n)"Sıralı liste" olarak adlandırdığınız "kırmızı-siyah ağaç" içinde bu davranışı nasıl elde edersiniz ?
ony

@ony "öğelerin sırasını tanımlayan sıralı liste ve dizi farklı miktarda bilgiye sahiptir." Evet, bu yüzden farklı performans özelliklerine sahipler. Konuyu kaçırıyorsun. Biri her durumda diğerinin yerine bir damla değildir. Bunlar farklı şeyler optimize ve farklı tavizlere yapmak ve nokta geliştiricileri sürekli bu ödünlerin ilgili kararlar olmasıdır.
jpmc26

@ony Erişim, arama, ekleme ve silme algoritma performansı bağlamında özel anlamlara sahiptir. Access, öğeyi konuma göre getiriyor. Arama, bir öğeyi değere göre bulmaktır (yalnızca harita dışı bir yapı için sınırlama denetimi olarak herhangi bir pratik uygulamaya sahiptir). Ancak ekleme ve silme işlemi basit olmalıdır. Örnek kullanım burada görülebilir .
jpmc26

23

Evet.

Gerçek bir durumda, hem kısa hem de uzun dize anahtarlarıyla tablo aramaları yapmak için bazı testler yaptık.

Bir std::map, a std::unordered_map, a dizginin uzunluğu boyunca en fazla 10 kez örnek veren bir karma (anahtarlarımız kılavuzlu olma eğilimindedir, bu yüzden bu iyi) ve her karakteri (teoride çarpışmaları azalttı) örnekleyen bir karma kullandık, bir ==karşılaştırma yaptığımız sıralanmamış bir vektör ve ayrıca bir hash sakladığımız sıralanmamış bir vektör, önce hash'ı karşılaştırın, sonra karakterleri karşılaştırın.

Bu algoritmalar O(1)(unordered_map) ile O(n)(doğrusal arama) arasında değişir .

Mütevazı boyutta N için, sıklıkla O (n) O (1) 'i geçer. Bunun nedeni, düğüm tabanlı kapların bilgisayarımızın bellekte daha fazla atlamasını gerektirdiği, ancak doğrusal tabanlı kapların gerektirmediğinden şüpheleniyoruz.

O(lg n)ikisi arasında var. Nasıl olduğunu hatırlamıyorum.

Performans farkı o kadar büyük değildi ve daha büyük veri setlerinde karma tabanlı olan çok daha iyi performans gösterdi. Bu yüzden karma tabanlı düzensiz haritaya saptık.

Uygulamada, makul büyüklükte n için, O(lg n)bir O(1). Bilgisayarınızda tablonuzda yalnızca 4 milyar giriş için yer varsa O(lg n), yukarıda sınırlandırılmıştır 32. (lg (2 ^ 32) = 32) (bilgisayar bilimlerinde, lg log tabanlı 2 için kısa eldir).

Pratikte, lg (n) algoritmaları logaritmik büyüme faktörü nedeniyle değil O (1) algoritmalarından daha yavaştır, çünkü lg (n) kısmı genellikle algoritmaya belirli bir karmaşıklık düzeyi anlamına gelir ve bu karmaşıklık bir lg (n) teriminden herhangi bir "büyüme" den daha büyük sabit faktör.

Bununla birlikte, karmaşık O (1) algoritmaları (karma eşleme gibi) kolayca benzer veya daha büyük bir sabit faktöre sahip olabilir.


21

Paralel olarak bir algoritma yürütme olasılığı.

Sınıflara örnek olup olmadığını bilmiyorum O(log n)veO(1) ancak bazı problemler için, algoritmanın paralel olarak yürütülmesi daha kolay olduğunda daha yüksek karmaşıklık sınıfına sahip bir algoritma seçersiniz.

Bazı algoritmalar paralel hale getirilemez ancak karmaşıklık sınıfı çok düşüktür. Aynı sonucu elde eden ve kolayca paralelleştirilebilen, ancak daha yüksek bir karmaşıklık sınıfına sahip olan başka bir algoritmayı düşünün. Bir makinede yürütüldüğünde, ikinci algoritma daha yavaştır, ancak birden çok makinede yürütüldüğünde, ilk algoritma hızlanamazken gerçek yürütme süresi azalır.


Fakat tüm bu paralelleşme, diğerlerinin konuştuğu sabit faktörü azaltmaktır, değil mi?
gengkev

1
Evet, ancak paralel bir algoritma, çalışan makinelerin sayısını her ikiye katladığınızda sabit faktörü 2'ye bölebilir. Başka bir tek iş parçacıklı algoritma, sabit faktörü sabit bir şekilde sadece bir kez azaltabilir. Böylece paralel bir algoritma ile n boyutuna dinamik olarak tepki verebilir ve duvar saati yürütme süresinde daha hızlı olabilirsiniz.
Taklit

15

Diyelim ki, 0 ile 1.000.000 arasındaki sayıların kara listeye alınabileceği gömülü bir sisteme bir kara liste uyguluyorsunuz. Bu size iki seçenek sunar:

  1. 1.000.000 bitlik bir bit kümesi kullanın
  2. Kara listeye alınmış tamsayıların sıralı bir dizisini kullanın ve bunlara erişmek için bir ikili arama kullanın

Bit kümesine erişim, sürekli erişimi garanti edecektir. Zaman karmaşıklığı açısından en uygunudur. Hem teorik hem de pratik bir bakış açısından (son derece düşük sabit bir yük ile O (1)).

Yine de ikinci çözümü tercih etmek isteyebilirsiniz. Özellikle kara listeye alınmış tamsayıların sayısının çok az olmasını beklerseniz, bellekte daha verimli olacağından.

Ve hafızanın az olduğu gömülü bir sistem için geliştirmeseniz bile, sadece 1.000.000 ila 1.000.000.000.000 arasındaki keyfi sınırı artırabilir ve aynı argümanı yapabilirim. Daha sonra bit seti yaklaşık 125G bellek gerektirir. O (1) garantili en kötü durum karmaşıklığına sahip olmak, patronunuzu size bu kadar güçlü bir sunucu sağlamaya ikna etmeyebilir.

Burada, O (1) bit kümesi yerine bir ikili aramayı (O (log n)) veya ikili ağacı (O (log n)) tercih ederim. Ve muhtemelen, O (n) 'nin en kötü durum karmaşıklığına sahip bir karma tablo, uygulamada hepsini yenecektir.



12

İnsanlar sorunuzu tam olarak yanıtladı, bu yüzden buraya geldiklerinde insanların gerçekten düşünebileceği biraz farklı bir sorunun üstesinden geleceğim.

"O (1) zaman" algoritmalarının ve veri yapılarının çoğu aslında sadece beklenen O (1) zamanını alır, yani ortalama çalışma sürelerinin O (1) olduğu , muhtemelen sadece belirli varsayımlar altında.

Ortak örnekler: karma tablolar, "dizi listelerinin" genişletilmesi (dinamik olarak boyutlandırılmış diziler / vektörler olarak da bilinir).

Bu tür senaryolarda, ortalama olarak daha kötü performans göstermelerine rağmen , zamanlarının kesinlikle logaritmik olarak sınırlandırılması garanti edilen veri yapılarını veya algoritmaları kullanmayı tercih edebilirsiniz.
Bu nedenle bir örnek, çalışma süresi ortalama olarak daha kötü ancak en kötü durumda daha iyi olan dengeli bir ikili arama ağacı olabilir.


11

Daha genel bir soru, kişinin bir O(f(n))algoritmayı algoritmaya tercih edeceği durumlar O(g(n))olsa dag(n) << f(n) olarak nsonsuza eğilimindedir. Diğerleri zaten söylediğim gibi cevap açıkça durumda "evet" f(n) = log(n)ve g(n) = 1. f(n)Polinom olan ancak g(n)üstel olan durumlarda bile bazen evettir . Ünlü ve önemli bir örnek doğrusal programlama problemlerini çözmek için Simplex Algoritmasıdır . 1970'lerde olduğu gösterilmiştir O(2^n). Bu nedenle, en kötü durum davranışı mümkün değildir. Ancak - ortalama vaka davranışı, on binlerce değişken ve kısıtlama ile ilgili pratik problemler için bile son derece iyidir. 1980'lerde polinom zaman algoritmaları ( Karmarkar'ın iç nokta algoritması) doğrusal programlama için keşfedildi, ancak 30 yıl sonra simpleks algoritması hala tercih edilen algoritma gibi görünüyor (bazı çok büyük problemler hariç). Bu, ortalama durum davranışının genellikle daha kötü durum davranışından daha önemli olduğu açık bir nedendir, ancak aynı zamanda simpleks algoritmanın bir anlamda daha bilgilendirici olması (ör. Duyarlılık bilgilerinin çıkarılması daha kolaydır).


10

Benim 2 sent koymak için:

Bazen algoritma belirli bir donanım ortamında çalıştığında daha iyi bir karmaşıklık algoritması seçilir. Sorunumuzu çözmek için O (1) algoritmamızın çok büyük, sabit boyutlu bir dizinin her öğesine ardışık olarak erişmediğini varsayalım. Ardından bu diziyi mekanik bir sabit sürücüye veya manyetik bir banda koyun.

Bu durumda, O (logn) algoritması (diske sırayla eriştiğini varsayalım), daha uygun hale gelir.


Burada sıralı erişim sürücüsünde veya bantta O (1) algoritmasının yerine O (n) olduğunu ekleyebilirim, bu yüzden sıralı çözüm daha uygun hale gelir. Birçok O (1) işlemi, sıralı erişim alanında bulunmayan sabit zamanlı bir algoritma olan eklemeye ve dizine alınmış aramaya bağlıdır.
TheHansinator

9

O (1) algoritması yerine O (log (n)) algoritması kullanmak için çok sayıda diğer cevabın göz ardı ettiği iyi bir kullanım durumu vardır: değişmezlik. Hash haritalarında O (1) vardır ve hash değerlerinin iyi dağılımını varsayar, ancak değişebilir duruma ihtiyaç duyarlar. Değişmez ağaç haritalarının asimptotik olarak daha yavaş olan O (log (n)) koyar ve alır. Bununla birlikte, değişmezlik, daha kötü performans için telafi edecek kadar değerli olabilir ve haritanın birden fazla versiyonunun tutulması gerektiğinde, değişmezlik, haritayı kopyalamaktan kaçınmanıza izin verir, bu O (n) ve bu nedenle iyileştirebilir verim.


9

Basitçe: Çünkü katsayı - kurulum, depolama ve bu adımın yürütme süresi ile ilişkili maliyetler - daha büyük olandan daha küçük bir büyük O problemiyle çok daha büyük olabilir. Big-O algoritma ölçeklenebilirliğinin sadece bir ölçüsüdür .

Hacker Sözlüğü'nden Kuantum Mekaniğinin Çoklu Dünya Yorumuna dayanan bir sıralama algoritması öneren aşağıdaki örneği düşünün :

  1. Bir kuantum işlemi kullanarak diziye rastgele izin ver,
  2. Dizi sıralanmamışsa, evreni yok edin.
  3. Kalan tüm evrenler artık [bulunduğunuz dünya dahil) sıralanmıştır.

(Kaynak: http://catb.org/~esr/jargon/html/B/bogo-sort.html )

Bu algoritmanın big-O olduğuna dikkat edin. Bu O(n), bilinen herhangi bir sıralama algoritmasını genel öğeler üzerinde bugüne kadar yener. Doğrusal adımın katsayısı da çok düşüktür (çünkü sadece bir karşılaştırma, bir takas değil, doğrusal olarak yapılır). Benzer bir algoritma, aslında, her ikisi de herhangi bir sorunu çözmek için kullanılabilir NP ve ko-NP , her olası bir çözüm, çünkü polinom zamanda (ya da herhangi bir çözüm yoktur mümkün geçirmez) kuantum işlemi kullanılarak üretilebilir, daha sonra belirlenmiş polinom zamanı.

Bununla birlikte, çoğu durumda, muhtemelen 2. adımı uygulama eyleminin hala "okuyucu için bir egzersiz olarak kaldığından" bahsetmiyoruz bile, Çoklu Dünyaların doğru olmayabileceği riskini almak istemiyoruz.


7

N'nin sınırlandığı ve O (1) algoritmasının sabit çarpanının log (n) 'deki sınırdan daha yüksek olduğu herhangi bir noktada. Örneğin, değerlerin bir karma kümesinde depolanması O (1) 'dir, ancak karma işlevinin pahalı bir hesaplanmasını gerektirebilir. Veri öğeleri önemsiz bir şekilde karşılaştırılabilirse (bazı siparişlere göre) ve n üzerindeki sınır, log n'nin herhangi bir öğedeki karma hesaplamasından önemli ölçüde daha az olması durumunda, dengeli bir ikili ağaçta depolamak, depolamaktan daha hızlı olabilir bir hashset.


6

Sağlam bir üst sınıra ihtiyaç duyduğunuz gerçek zamanlı bir durumda, örneğin bir Quicksort'un aksine bir yığın seçersiniz, çünkü yığının ortalama davranışı da en kötü durum davranışıdır.


6

Zaten iyi cevaplara ekleme Pratik bir örnek postgres veritabanındaki Hash dizinleri ve B-ağacı dizinleri olacaktır.

Karma dizinler, adından da anlaşılacağı gibi btree bir Btree veri yapısı kullandığında diskteki verilere erişmek için bir karma tablo dizini oluşturur.

Big-O zamanında bunlar O (1) ve O (logN) 'dir.

Hash dizinleri şu anda postgreslerde cesaretini kırıyor, çünkü özellikle veritabanı sistemlerinde gerçek bir yaşam durumunda, çarpışma olmadan karma elde etmek çok zor (O (N) en kötü durum karmaşıklığına yol açabilir) ve bu nedenle, yapmak daha da zor güvenli çöküyorlar (yazma öncesinde günlüğe kaydetme denir - postgreslerde WAL).

Bu takas bu durumda yapılır çünkü O (logN) indeksler için yeterince iyidir ve O (1) 'in uygulanması oldukça zordur ve zaman farkı gerçekten önemli değildir.



3
  1. O (1) 'deki "1" çalışma ünitesi O (çalışma n)' deki çalışma ünitesine göre çok yüksek olduğunda ve beklenen ayar boyutu küçük-ish olduğunda. Örneğin, yalnızca iki veya üç öğe varsa Sözlük karma kodlarını hesaplamak diziyi yinelemekten daha yavaştır.

veya

  1. O (1) algoritmasındaki bellek veya diğer zaman dışı kaynak gereksinimleri, O (log n) algoritmasına göre istisnai derecede büyük olduğunda.

3
  1. Bir programı yeniden tasarlarken, bir prosedürün O (lgN) yerine O (1) ile optimize edildiği bulunur, ancak bu programın darboğazı değilse ve O (1) alg'ini anlamak zorsa. O zaman O (1) algoritmasını kullanmak zorunda kalmazsınız
  2. O (1), sağlayamayacağınız çok fazla belleğe ihtiyaç duyduğunda, O (lgN) zamanı kabul edilebilir.

1

Bu, birisinin bir soruna çok hızlı bir şekilde yanıt almasını önlemek için algoritmaları bilerek yavaş olan sorunları tasarlamak istediğimiz güvenlik uygulamaları için genellikle geçerlidir.

İşte kafamın üstünden birkaç örnek.

  • Parola karmaşası bazen parolaları kaba kuvvetle tahmin etmeyi zorlaştırmak için keyfi olarak yavaşlatılır. Bu Bilgi Güvenliği gönderisinde bununla ilgili bir madde işareti (ve daha fazlası) bulunur.
  • Bit Coin , madeni paraları "mayınlamak" için bilgisayar ağının çözmesi için kontrol edilebilir yavaş bir problem kullanır. Bu, para biriminin kolektif sistem tarafından kontrollü bir oranda çıkarılmasını sağlar.
  • Asimetrik şifreler ( RSA gibi ), özel anahtarı olmayan birisinin şifrelemeyi kırmasını önlemek için anahtarlar olmadan kasıtlı olarak şifre çözme yapmak üzere tasarlanmıştır. Algoritmalar , anahtarın bit uzunluğunun (bu kaba kuvvet) umarım O(2^n)zamanında kırılacak şekilde tasarlanmıştır n.

CS'nin başka yerlerinde, Hızlı Sıralama O(n^2)en kötü durumda ancak genel durumda O(n*log(n)). Bu nedenle, algoritma verimliliğini analiz ederken bazen “Büyük O” analizi önem vermez.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.