Herhangi bir O (1 / n) algoritması var mı?
Veya O (1) 'den daha düşük bir şey?
Herhangi bir O (1 / n) algoritması var mı?
Veya O (1) 'den daha düşük bir şey?
Yanıtlar:
Bu soru göründüğü kadar aptal değil. En azından teorik olarak , Büyük O gösteriminin matematiksel tanımını aldığımızda O (1 / n ) gibi bir şey tamamen mantıklıdır :
Şimdi kolayca yerine g ( x ) 1 / x ... Yukarıdaki tanım hala bazı için de geçerlidir aşikardır f .
Asimptotik çalışma zamanı büyümesini tahmin etmek amacıyla, bu daha az uygulanabilir… anlamlı bir algoritma girdi büyüdükçe daha hızlı olamaz. Elbette, bunu gerçekleştirmek için rasgele bir algoritma oluşturabilirsiniz, örneğin aşağıdakiler:
def get_faster(list):
how_long = (1 / len(list)) * 100000
sleep(how_long)
Açıkçası, bu işlev giriş boyutu büyüdükçe daha az zaman harcar ... en azından donanım tarafından zorlanan bir sınıra kadar (sayıların hassasiyeti sleep
, bekleyebilecek minimum süre, bağımsız değişkenleri işleme süresi vb.): Bu sınır daha sonra bir sabit alt sınır dolayısıyla aslında yukarıdaki fonksiyon hala çalışma zamanı O (1) 'e sahiptir.
Ama olan çalışma zamanı (kısmen en azından) azaltabilir aslında gerçek dünya algoritmaları giriş boyutu artar. Bu algoritmalar olacağı Not olup aşağıdaki çalışma zamanı davranış sergileyen O da, (1). Yine de ilginçler. Örneğin, Horspool'un çok basit metin arama algoritmasını ele alalım . Burada, arama modelinin uzunluğu arttıkça beklenen çalışma süresi azalacaktır (ancak samanlığın artan uzunluğu çalışma süresini bir kez daha artıracaktır).
Evet.
Çalışma zamanı O (1 / n) olan "boş" algoritma ile tam olarak bir algoritma vardır.
Bir algoritmanın O (1 / n) olması, tek bir komuttan oluşan algoritmadan daha az adımda asimptotik olarak yürütüldüğü anlamına gelir. Tüm n> n0 için bir adımdan daha az adımda yürütülürse, bu n için kesinlikle hiçbir talimat içermemelidir. 'N> n0' öğesinin kontrol edilmesi en az 1 talimat gerektirdiğinden, tüm n için talimat içermemelidir.
Özet olarak: O, (1 / n) sadece bir algoritma oluşan boş algoritmadır bir talimat.
keskin dişler doğrudur, O (1) mümkün olan en iyi performanstır. Bununla birlikte, hızlı bir çözüm değil, sadece sabit bir zaman çözümü anlamına gelir.
İlginç bir varyant ve belki de gerçekten önerilen şey , nüfus büyüdükçe sorunların daha kolay hale gelmesidir. Ben düşünülmüş olsa da, yan yana dil 1 cevap düşünebilirsiniz:
Sette iki kişinin aynı doğum günü var mı? N 365'i aştığında true değerini döndürün. 365'den az olmasına rağmen, bu O (n ln n) 'dir. Belki de büyük bir cevap değil, çünkü sorun yavaş yavaş kolaylaşmıyor, ancak n> 365 için O (1) oluyor.
Bu mümkün değil. Big-O'nun tanımı eşitsizlikten daha büyük değildir :
A(n) = O(B(n))
<=>
exists constants C and n0, C > 0, n0 > 0 such that
for all n > n0, A(n) <= C * B(n)
Dolayısıyla B (n) aslında maksimum değerdir, bu nedenle n arttıkça azalırsa tahmin değişmez.
Önceki büyük O gösterimi öğrenmemden, 1 adıma (bir değişkeni kontrol etmek, bir ödev yapmak gibi) ihtiyacınız olsa bile, O (1).
O (1) 'in O (6) ile aynı olduğunu unutmayın, çünkü "sabit" önemli değildir. Bu yüzden O (n) 'nin O (3n) ile aynı olduğunu söylüyoruz.
Yani 1 adıma bile ihtiyacınız varsa, bu O (1) ... ve programınız en az 1 adıma ihtiyaç duyduğundan, bir algoritmanın gidebileceği minimum değer O (1) 'dir. Yapmazsak, O (0), sanırım? Hiç bir şey yapmazsak, O (1) olur ve gidebileceği en düşük şey budur.
(Bunu yapmamayı seçersek, o zaman bir Zen veya Tao sorusu olabilir ... programlama alanında, O (1) hala minimumdur.
Ya da bunun hakkında:
programcı : patron, O (1) zamanında yapmak için bir yol buldum!
patron : Buna gerek yok, bu sabah iflas ediyoruz.
programcı : oh o zaman O (0) olur.
Hayır, bu mümkün değil:
N, 1 / n cinsinden sonsuzluğa eğilimli olduğu için, sonunda etkili bir şekilde 0 olan 1 / (inf) elde ederiz.
Böylece, problemin büyük-oh sınıfı, büyük bir n ile O (0) olacaktır, ancak düşük bir n ile sabit zamana daha yakın olacaktır. Sabit zamandan daha hızlı bir şekilde yapılabilecek tek şey şu: Bu mantıklı değil:
void nothing() {};
Ve bu bile tartışmalı!
Bir komutu yürüttüğünüz anda, en az O (1) içerisindesiniz, yani hayır, büyük bir oh (O / 1) sınıfı olamaz!
Fonksiyonu hiç çalıştırmamaya ne dersiniz (NOOP)? veya sabit bir değer kullanarak. Bu sayılır mı?
Girişler büyüdükçe küçülen olasılıkları tanımlamak için genellikle O (1 / n) kullanıyorum - örneğin, log2 (n) döndürmelerde adil bir paranın kuyruk bulma olasılığı O (1 / n).
O (1) basitçe "sabit zaman" anlamına gelir.
Bir döngüye [1] erken bir çıkış eklediğinizde (büyük O gösteriminde) bir O (1) algoritmasını O (n) 'ye dönüştürürsünüz, ancak daha hızlı hale getirirsiniz.
Hile genel olarak sabit zaman algoritması en iyisidir ve lineer üstelden daha iyidir, ancak küçük miktarlarda n için üstel algoritma aslında daha hızlı olabilir.
1: Bu örnek için statik bir liste uzunluğu olduğu varsayılarak
Bu soruyu okuyan ve konuşmanın ne hakkında olduğunu anlamak isteyen herkes için bu yardımcı olabilir:
| |constant |logarithmic |linear| N-log-N |quadratic| cubic | exponential |
| n | O(1) | O(log n) | O(n) |O(n log n)| O(n^2) | O(n^3) | O(2^n) |
| 1 | 1 | 1 | 1| 1| 1| 1 | 2 |
| 2 | 1 | 1 | 2| 2| 4| 8 | 4 |
| 4 | 1 | 2 | 4| 8| 16| 64 | 16 |
| 8 | 1 | 3 | 8| 24| 64| 512 | 256 |
| 16 | 1 | 4 | 16| 64| 256| 4,096 | 65536 |
| 32 | 1 | 5 | 32| 160| 1,024| 32,768 | 4,294,967,296 |
| 64 | 1 | 6 | 64| 384| 4,069| 262,144 | 1.8 x 10^19 |
Kuantum algoritmalarının süperpozisyonla "bir kerede" birden fazla hesaplama yapabileceğine inanıyorum ...
Bunun yararlı bir cevap olduğundan şüpheliyim.
birçok kişi doğru cevaba sahipti (Hayır) Bunu kanıtlamanın başka bir yolu var: Bir fonksiyona sahip olmak için, fonksiyonu çağırmanız gerekir ve bir cevap vermeniz gerekir. Bu sabit bir süre alır. İŞLEMİN geri kalan kısmı daha büyük girdiler için daha az zaman aldıysa, yanıtı yazdırmak (yani tek bir bit olduğunu varsayabiliriz) en az sabit zaman alır.
Nüfus arttıkça hangi sorunlar daha kolaylaşır? Bir cevap, indirme hızının düğüm sayısının ters bir işlevi olduğu bittorrent gibi bir şeydir. Ne kadar çok yüklerseniz onu yavaşlatan bir arabanın aksine, bittorrent gibi bir dosya paylaşım ağı o kadar fazla düğümü bağlar.
O (1) in altına inemezsiniz, ancak k, N'den küçük olduğunda O (k) mümkündür. Onlara alt doğrusal zaman algoritmaları adını verdik . Bazı problemlerde, Alt Doğrusal zaman algoritması belirli bir soruna sadece yaklaşık çözümler verebilir. Bununla birlikte, bazen, muhtemelen veri kümesi çok büyük olduğu veya hepsini hesaplamak için çok fazla hesaplama pahalı olduğu için yaklaşık çözümler iyi olur.
Peki buna ne dersin:
void FindRandomInList(list l)
{
while(1)
{
int rand = Random.next();
if (l.contains(rand))
return;
}
}
listenin boyutu büyüdükçe, programın beklenen çalışma süresi azalır.
constains
O (1)
O (1 / n), O (1) 'den daha az değildir, temelde daha fazla veriye sahip olduğunuzda, algoritmanın daha hızlı gittiği anlamına gelir. Bir dizi aldığınızı ve ondan daha azına sahipse her zaman 10 100 öğeye kadar doldurduğunu ve daha fazlası varsa hiçbir şey yapmadığını varsayalım. Bu elbette O (1 / n) değil, O (-n) gibi bir şey :) Çok kötü O-büyük gösterim negatif değerlere izin vermiyor.
Belirtildiği gibi, null işlevinin olası istisnası dışında, O(1/n)
0'a yaklaşmak zorunda kalacağı için hiçbir işlev olamaz .
Tabii ki, Konrad tarafından tanımlanan gibi O(1)
, en azından bir anlamda daha az olması gerektiği gibi görünen bazı algoritmalar var .
def get_faster(list):
how_long = 1/len(list)
sleep(how_long)
Bu algoritmaları araştırmak istiyorsanız, kendi asimtotik ölçümünüzü veya kendi zaman kavramınızı tanımlamanız gerekir. Örneğin, yukarıdaki algoritmada, bir dizi "serbest" işlemin belirli bir süre kullanılmasına izin verebilirim. Yukarıdaki algoritmada, uykuyu hariç her şeyin zamanını hariç tutarak t 'yi tanımlarsam, o zaman t' = 1 / n, yani O (1 / n). Asimptotik davranış önemsiz olduğu için muhtemelen daha iyi örnekler vardır. Aslında, eminim oradaki biri önemsiz olmayan sonuçlar veren duyular ortaya çıkarabilir.
Cevapların çoğu big-O'nun sadece bir algoritmanın çalışma süresi ile ilgili olduğunu yorumlar. Ancak sorudan bahsetmediği için, sayısal analizde big-O'nun diğer uygulamasından bahsetmeye değer olduğunu düşündüm, bu da hata ile ilgilidir.
Adım boyutu (h) veya bölüm sayısı (n) hakkında konuşup konuşmamanıza bağlı olarak, birçok algoritma O (h ^ p) veya O (n ^ {- p}) olabilir. Örneğin, Euler yönteminde , y (0) ve dy / dx'i (y türevi) bildiğiniz göz önüne alındığında, bir y (h) tahmini ararsınız. Y (h) tahmininiz h, 0'a yaklaştıkça daha doğrudur. Bu nedenle, bazı rastgele x için y (x) bulmak için 0 ila x aralığını alır, n parçaya kadar böler ve Euler yöntemini çalıştırır her noktada, y (0) 'dan y (x / n)' ye y (2x / n) 'ye, vb. gitmek için.
Dolayısıyla Euler yöntemi O (h) veya O (1 / n) algoritmasıdır, burada h tipik olarak bir adım boyutu olarak yorumlanır ve n bir aralığı bölme sayısı olarak yorumlanır.
Kayan nokta yuvarlama hataları nedeniyle gerçek sayısal analiz uygulamalarında O (1 / sa) da olabilir . Aralığınızı ne kadar küçük yaparsanız, belirli algoritmaların uygulanması için daha fazla iptal, daha fazla önemli basamak kaybı ve dolayısıyla algoritma yoluyla yayılan daha fazla hata oluşur.
Euler yöntemi için, kayan noktalar kullanıyorsanız, yeterince küçük bir adım ve iptal kullanın ve büyük bir sayıya küçük bir sayı ekleyerek büyük sayıyı değiştirmeyin. İki çok yakın konumda değerlendirilen bir fonksiyondan iki sayıyı birbirinden çıkararak türevi hesaplayan algoritmalar için, y '(x)' i (y (x + h) - y (x) / h) ile pürüzsüz fonksiyonlarda y (x + h) y'ye (x) yaklaşır, bu da büyük iptal ve daha az önemli rakamlara sahip türev için bir tahmin sağlar. Bu da türev için ihtiyaç duyduğunuz algoritmaya (örneğin bir sınır değer problemi) yayılacaktır.
Tamam, biraz düşünmüştüm ve belki de bu genel formu takip edebilecek bir algoritma var:
1000 düğümlü bir grafik için seyahat eden satıcı problemini hesaplamanız gerekir, ancak ziyaret edemeyeceğiniz düğümlerin bir listesi de verilir. İstenmeyen düğümlerin listesi büyüdükçe, sorunun çözülmesi daha kolay hale gelir.
Kuşkusuz bir üst sınır O (1 / n) olan bir algoritma görüyorum:
Rutin dışında bir şey nedeniyle değişen büyük bir dizi girdiniz var (belki donanımı yansıtıyorlar veya hatta işlemcide bunu yapan başka bir çekirdek bile olabilirler) ve rastgele ama geçerli bir tane seçmelisiniz.
Şimdi, eğer değişmemiş olsaydı, öğelerin bir listesini yaparsınız, rastgele birini seçer ve O (1) zamanı alırsınız. Ancak, verilerin dinamik doğası bir liste yapmayı engeller, sadece rastgele prob yapmanız ve probun geçerliliğini test etmeniz gerekir. (Ve doğası gereği cevabın geri döndüğünde hala geçerli olduğuna dair bir garanti olmadığına dikkat edin. Bu, hala oyundaki bir birimin yapay zekâsı için de kullanılabilirdi. tetiği çekmek.)
Bu, en kötü durum sonsuzluk performansına sahiptir, ancak veri alanı doldukça azalan ortalama bir durum performansına sahiptir.
Sayısal analizde, yaklaşım algoritmalarının yaklaşık toleransta alt-sabit asimptotik karmaşıklığa sahip olması gerekir.
class Function
{
public double[] ApproximateSolution(double tolerance)
{
// if this isn't sub-constant on the parameter, it's rather useless
}
}
Sanırım O (1) 'den daha az mümkün değil. Algo tarafından alınan her zaman O (1) olarak adlandırılır. Ancak O (1 / n) için aşağıdaki fonksiyona ne dersiniz. (Bu çözümde halihazırda sunulan birçok varyant olduğunu biliyorum, ama sanırım hepsinin bazı kusurları var (büyük değil, konsepti iyi açıklıyorlar). İşte bir tane, sadece tartışma uğruna:
def 1_by_n(n, C = 10): #n could be float. C could be any positive number
if n <= 0.0: #If input is actually 0, infinite loop.
while True:
sleep(1) #or pass
return #This line is not needed and is unreachable
delta = 0.0001
itr = delta
while delta < C/n:
itr += delta
Böylece n arttıkça fonksiyon daha az zaman alacaktır. Ayrıca giriş gerçekten 0 ise, fonksiyonun geri dönmesi sonsuza kadar sürecektir.
Makinenin hassasiyeti ile sınırlandırılacağı iddia edilebilir. böylece iç mekanın üst sınırı vardır O (1). Ancak bunu, dizideki n ve C girişlerini alarak atlayabiliriz. Ve toplama ve karşılaştırma string üzerinde yapılır. Fikir şu ki, bununla n'yi keyfi olarak küçük azaltabiliriz. Bu nedenle, n = 0'ı görmezden gelsek bile, işlevin üst sınırı sınırlı değildir.
Ayrıca sadece çalışma süresinin O (1 / n) olduğunu söyleyemeyeceğimize inanıyorum. Ama O (1 + 1 / n) gibi bir şey söylemeliyiz
O (1 / n) olan bir algoritma oluşturmak mümkün olabilir. Bir örnek, f (n) 'nin birkaç katını yineleyen bir döngü olacaktır; burada f (n), değerinin n'den büyük olacağı garanti edilen bir işlevdir ve n, sonsuzluğa yaklaştıkça f (n) -n sınırı sıfır. F (n) hesaplamasının da tüm n için sabit olması gerekir. Elimde f (n) neye benzeyeceğini veya böyle bir algoritmanın hangi uygulamaya sahip olacağını bilmiyorum, ancak bence böyle bir fonksiyon var olabilir, ancak ortaya çıkan algoritmanın bir algoritma olasılığını kanıtlamaktan başka bir amacı olmayacaktır. O (1 / n).
Algoritmalar hakkında bilmiyorum ama rastgele algoritmalarda O (1) den daha az karmaşıklık görünüyor. Aslında o (1) (küçük o) O (1) 'den daha azdır. Bu tür karmaşıklık genellikle rastgele algoritmalarda görülür. Örneğin, dediğin gibi, bir olayın olasılığı 1 / n derece olduğunda, o (1) ile gösterirler. Veya yüksek olasılıkla bir şey olduğunu söylemek istediklerinde (örneğin 1 - 1 / n) bunu 1 - o (1) ile gösterirler.
Giriş verilerinden bağımsız olarak cevap aynıysa, O (0) algoritmanız vardır.
ya da başka bir deyişle - girdi verileri gönderilmeden önce cevap biliniyor - fonksiyon optimize edilebilir - böylece O (0)
Big-O gösterimi , bir algoritmanın tipik çalışma süresiyle aynı olmayan en kötü senaryoyu temsil eder . Bir O (1 / n) algoritmasının bir O (1) algoritması olduğunu kanıtlamak kolaydır. Tanım olarak,
O (1 / n) -> T (n) <= 1 / n, tüm n> = C> 0
O (1 / n) -> T (n) <= 1 / C, 1 / n <= 1 / C tüm n> = C
O (1 / n) -> O (1) içindir, çünkü Big-O gösterimi sabitleri yok sayar (yani C değeri önemli değildir)
hashtable-contains
Algoritmanın O (1) olarak gösterilebilen beklenen (ve ortalama) çalışma zamanını düşünün - en kötü durum Theta (n) olarak çok kesin olarak verilebilir! Omega ve Theta sadece diğer sınırları belirtmek için kullanılabilir, ancak tekrar söylemek gerekirse : ortalama veya en iyi durumla ilgisi yoktur.
Hiçbir şey O'dan küçük değildir (1) Big-O notasyonu bir algoritma için en büyük karmaşıklık sırasını ima eder
Bir algoritmanın çalışma zamanı n ^ 3 + n ^ 2 + n + 5 ise, O (n ^ 3) 'dir. Burada düşük güçler önemli değildir çünkü n -> Inf olarak, n ^ 2, n ^ 3
Aynı şekilde n -> Inf gibi, O (1 / n) O (1) ile ilgisiz olacaktır, bu nedenle 3 + O (1 / n) O (1) ile aynı olacaktır, böylece O (1) mümkün olan en küçük hesaplama yapar karmaşa
inline void O0Algorithm() {}
İşte basit bir O (1 / n) algoritması. Ve hatta ilginç bir şey yapar!
function foo(list input) {
int m;
double output;
m = (1/ input.size) * max_value;
output = 0;
for (int i = 0; i < m; i++)
output+= random(0,1);
return output;
}
O (1 / n), artan girdi boyutu göz önüne alındığında bir fonksiyonun çıkışının nasıl değiştiğini açıkladığı için mümkündür. Bir fonksiyonun yürüttüğü talimat sayısını tanımlamak için 1 / n fonksiyonunu kullanırsak, fonksiyonun herhangi bir giriş boyutu için sıfır talimat almasına gerek yoktur. Daha ziyade, her bir giriş boyutu için, bir eşiğin üzerindeki n, gerekli talimat sayısının yukarıda 1 / n ile çarpılan pozitif bir sabitle sınırlandırılmasıdır. 1 / n'nin 0 olduğu ve sabitin pozitif olduğu gerçek bir sayı olmadığından, işlevin 0 veya daha az talimat almak için kısıtlanmasının bir nedeni yoktur.