2010-10-28 25 views
7

Olası Yinelenen:
Quickest way to find missing number in an array of numbersZor algoritma soru

Girdi: sıralanmamış dizi bir [1, .., n] aralığı 0 tamsayılar biri hariç tümünü içerir, .., n

Sorun, O (n) zamanındaki eksik tam sayıyı saptamaktır. A'nın her elemanı, ikili olarak temsil edilen 'dur ve kullanılabilir olan tek işlem, 'un A [i] jth biti değerini döndürdüğü ve sabit zaman aldığı işlev biti (i, j) 'dir.

Herhangi bir fikrin var mı? Bir çeşit böl ve yönet algoritmasının uygun olacağını düşünüyorum, ama tam olarak ne yapmam gerektiğini düşünemiyorum. Şimdiden teşekkürler!

+5

n (n + 1)/2 - toplam;) – AraK

+0

Eğer bit (i, j) YALNIZCA kullanılabilir durumda ise, böl ve yönet algoritmasını nasıl uygulayacaksınız? –

+0

@A. Rex: Bağladığınız olası dupe, talimatlarda aynı kısıtlamaya sahip değil, bu yüzden mutlaka bir dupe olduğunu sanmıyorum. –

cevap

9

O nn(n+1)/21 ve n arasındaki sayıların toplamıdır matematiksel bir mülk. Sen 10 için bu görebilirsiniz: sadece buna 0 ekliyoruz beri

1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 
= (1+10) + (2+9) + (3+8) +(4+7) + (5+6) 
= 11 + 11 + 11 + 11 + 11 
= 55 

Yani, uzantısı, n aracılığıyla 0 gelen sayıların toplamıdır. Yani yaptığınız şey, tüm sayıları toplayıp sayım yapmaktır, sonra eksik olanı bulmak için bu formülü kullanır.

Yani, gibi bir şey: tek tek bit ayıklamak ve toplanmasıyla gerçek sayılar bunları açmak gerekecek böylece bit(i,j) ile numarası alınıyor

count = 0 
sum = 0 
foreach num in list: 
    sum = sum + num 
    count = count + 1 
missing = count * (count+1)/2 - sum 

zordur.

+0

Bu, A'nın tüm n log n bitlerini okur, bu yüzden log n zaman alır. –

+1

@Reid: Hayır, n log n değil. N'yi hem bit sayısı hem de tamsayıların sayısı için kullanamazsınız. Bir tamsayıdaki bit sayısı _constant_, yani "O (n)" ile tam olarak aynı olan O (32n) '(32 bitlik bir sayı için). – paxdiablo

+0

OP'nin "tamsayı" yazması durumunda "tamsayı", "2^32'den küçük tam sayı" anlamına gelmediğinden eminim. Aksi takdirde, sadece son derece fazla olası giriş vardır, bu yüzden asimptotik çalışma zamanı hakkında konuşmak mantıklı değildir. Açıkça, bitlerdeki gerçek bir matematiksel tamsayı uzunluğu sabit değildir. –

0

Bu, bir bit sorusu, çünkü bit yöntemini kullanmak her bir sayı için her bir biti çevirmenizi gerektireceğinden, otomatik olarak O (n * j) olacak, yani j n'yi temsil eden bitlerin sayısıdır.

Sanırım paxdiablo'nun var, sanırım bit yöntemini kullanmayan bir çözüme izin veriliyor.

+3

Neil, bu teknik hala “O (n)” olurdu çünkü j' sabittir. – paxdiablo

+0

j pratikte sabittir, çünkü bir tamsayı veya uzunluğun uzunluğu her zaman aynıdır, ancak j'nin anlamlı basamakları n> 2 ile n = 2 ile artar. Daha fazla O (log n) gibi. – Neil

6

XOR operatörünü eklentiden daha hızlı olarak kullanabilirsiniz. Her bir bitime erişebildiğiniz için burada bitümlü bir XOR yapıyor olacaksınız. Burada kullanılacak ilkesi (A XOR B XOR A) = B

, örneğin: (1 XOR 2 XOR 3) bir XOR (1 XOR 2) = 3

for i=0 to n 
{ 
Total=Total XOR i 
} 

foreach element in A 
{ 
Total=Total XOR element 
} 
+0

Aslında, bu oldukça şık, +1. XOR'un eklenenden daha hızlı olacağına dair _sure_ olamazsınız, ancak XOR kullanan iki/en-bir-bir (örneğin, 91 91 82 82 73 64 64 55 55') varyasyonu için düzgün bir değişiklik singleton'u bulmak için. – paxdiablo

+1

Xor asla Eklemeden daha yavaş olmayacak ... Neden: Ayrıca bir adım ekleyerek tam bir toplayıcı gerektiren bir devir bit var ... Bu neredeyse aynı performansa sahip modern mimaride paralel toplayıcılar kullanılarak ortadan kaldırılır (xor kullanır Bu işlem için 1 kapı daha az) – Mulki

+0

1 ile n arasında XOR için bir O (1) formül var. http://stackoverflow.com/questions/3932346/direct-formula-for-summing-xor. XOR ayrıca taşma sorunlarını önler. –