Önceki 65 baytlık çözüm:
r->{for(int a,b=0,z,i=0;;b=a)if((a=b|1<<(z=r[i++]))==b)return z;}
Yeni çözüm 19 bayt dahilimport java.math.*;
@Nevay sayesinde -8 bayt
r->{int z,i=0;for(BigInteger c=BigInteger.ZERO;c.min(c=c.setBit(z=r[i++]))!=c;);return z;}
Çevrimiçi deneyin!
Düzenle
Orijinal programımdaki algoritma iyiydi, ancak kullanılan veri tipinin statik büyüklüğü, boyut belirli bir eşiğin üzerine çıktığında oldukça hızlı bir şekilde kırıldığı anlamına geliyordu.
Programın hafıza sınırını arttırmak için hesaplamada kullanılan veri tipini değiştirdim BigInteger
( int
veya yerine rastgele kesinlik için kullanmak long
). Bununla birlikte, bu durumun O(1)
uzay karmaşıklığı olarak sayılıp sayılmadığını tartışılabilir kılar .
Açıklamamı aşağıda tam olarak bırakacağım, ancak şimdi O(1)
bazı varsayımlar yapmadan uzay karmaşıklığına ulaşmanın imkansız olduğuna inanıyorum .
Kanıt
N
Öyle bir tamsayı olarak tanımlayın 2 <= N
.
Kısıtlamanın olduğu S
bir dizi rasgele tamsayıyı temsil eden bir liste olsun .[x{1}, ..., x{N}]
x{i}
1 <= x{i} <= N
Her öğe için tam olarak bir kez bu listeyi yinelemek için gereken zaman karmaşıklığı (Big-O notasyonunda) O(n)
Verilen zorluk, listedeki ilk kopyalanan değeri bulmaktır. Daha spesifik S
olarak, listedeki bir önceki öğenin kopyası olan ilk değeri arıyoruz .
Bu ve listede iki elementin pozisyonları olsun p
ve olsun . Mücadelemiz , bu koşulları karşılayan en küçüğü bulmak olur .q
p < q
x{p} == x{q}
q
Bu soruna açık olan yaklaşım S ile yineleme yapmak ve x{i}
başka bir listede var olup olmadığımızı kontrol etmektir T
: Eğer x{i}
yoksa T
, içinde saklıyoruz T
. Eğer x{i}
mevcut değil T
, bu nedenle ilk yinelenen değer ve küçüğüdür q
ve bu nedenle biz geri ver. Bu alan verimliliği O(n)
.
Zaman karmaşıklığını O(1)
korurken alan karmaşıklığını elde etmek için O(n)
, her nesne hakkında benzersiz bilgiyi sınırlı bir alanda saklamamız gerekir. Bu nedenle, herhangi bir algoritmanın gerçekleştirebileceği tek yolO(1)
boşluk karmaşıklığı şöyledir: 1. N, belirli bir sonlu veri türü için mümkün olan maksimum değer sayısını saklamak için gereken belleğe karşılık gelen bir üst sınır verilir. 2. Tek bir değişmez değişkenin yeniden atanması karmaşıklığa karşı sayılmaz, sadece değişkenlerin sayısı (bir liste birden fazla değişkendir). 3. (Diğer cevaplara dayanarak) Liste (veya en azından listenin elemanları) değişkendir ve listenin veri türü, listedeki öğelerde değişiklik yapılmasını sağlayan imzalı bir tamsayı olarak önceden ayarlanmıştır. ek bellek kullanmadan.
1 ve 3'ün her ikisi de veri türü hakkında varsayımlar ve spesifikasyonlar gerektirirken, 2 bu değişkenlerin büyüklüğü yerine alan karmaşıklığının hesaplanması için sadece değişkenlerin sayısının dikkate alınmasını gerektirir. Bu varsayımların hiçbiri kabul edilmezse, hem O(n)
zaman karmaşıklığına hem de O(1)
mekan karmaşıklığına ulaşmak imkansız olacaktır .
açıklama
Kim çocuğum, bu biraz beyin gücü düşünmek için çok utanç verici bir zaman aldı .
Bu yüzden bonusu almak zordur. Biz de tam olarak listenin tamamının üzerinde çalışmasına gerek ve biz zaten ek alan karmaşıklığı olmadan iterated ettik değerleri iz.
Bit manipülasyon bu sorunları çözer. O(1)
Bir çift tamsayı olan 'depolamamızı' başlattıktan sonra listeyi yineledik, ith bitini ilk tamsayıya yerleştirip ikincisini sakladık.
Mesela 1101
bizde bir VEYA işlemi gerçekleştirirsek 10
, anlıyoruz 1111
. Başka bir VEYA ile 10
yaparsak, yine de sahibiz 1101
.
Ergo, OR işlemini yaptığımızda ve aynı numara ile bittikten sonra, kopyamızı bulduk. Dizideki hiçbir kopya, programın çalışıp bir istisna atmasına neden olmaz.