2011-05-15 6 views
6

O (1) 'de m-element kombinasyonunun k-inci elemanını elde etmenin herhangi bir yolunu biliyor musunuz? Beklenen çözüm, herhangi bir giriş verisi boyutu ve herhangi bir m değeri için çalışmalıdır. abd olan belirli bir verilerine k-th (bu örnekte 2-nd) m-eleman kombinasyonunun elemanı içinO (1) 'de m-karakter uzunluğunun k-th elemanını almak mümkün mü?

>>> import itertools 
>>> data = ['a', 'b', 'c', 'd'] 
>>> k = 2 
>>> m = 3 
>>> result = [''.join(el) for el in itertools.combinations(data, m)] 
>>> print result 
['abc', 'abd', 'acd', 'bcd'] 
>>> print result[k-1] 
abd 

:

beni (piton kodu) örnek bu sorunu açıklayalım. Tüm birleştirici listeyi oluşturmadan bu değeri (abd) mümkün mü?

Ben ~ 1.000.000 karakter veri var ve k-inci elemanı almak için tam m karakterlik uzunlukta kombinatoriyel liste oluşturmak mümkün değildir, çünkü bi'şey soran.

çözüm sözde kodu veya bir bağlantı, bu sorunu (ne yazık ki, bulamadım) açıklayan sayfa olabilir.

Teşekkürler!

+2

Bunu yapmak için, kombinasyonlar için iyi tanımlanmış bir sıraya ihtiyacınız vardır. –

cevap

1

İlle O (1), ama çok hızlı olması gerekir:

özgün kombinasyonlar algoritması al: n başlangıç ​​elemanları ve m kombine uzunluğu için

def combinations(elems, m): 
    #The k-th element depends on what order you use for 
    #the combinations. Assuming it looks something like this... 
    if m == 0: 
     return [[]] 
    else: 
     combs = [] 
     for e in elems: 
      combs += combinations(remove(e,elems), m-1) 

, elimizdeki n!/(n-m)!m! toplam kombinasyonları . Bizim arzu birleşmesine doğrudan atlamak için bu gerçeği kullanabilirsiniz:

def kth_comb(elems, m, k): 
    #High level pseudo code 
    #Untested and probably full of errors 
    if m == 0: 
     return [] 
    else: 
     combs_per_set = ncombs(len(elems) - 1, m-1) 
     i = k/combs_per_set 
     k = k % combs_per_set 
     x = elems[i] 
     return x + kth_comb(remove(x,elems), m-1, k) 
0

ilk elemanların

miktarı n r = !n/(!m*!(n-m)) hesaplamak

sonra kat (r/k) sonucu ilk elemanın endeksidir ,

kaldırmak

do M-, n- ve k = r% k

ve yineleme (sola aşağıdaki herşeyi vardiya) m

5

http://en.wikipedia.org/wiki/Permutation#Numbering_permutations

Temel olarak 0 (k, 0, sadece sonucu aşağıdaki karakter kopya olan ipucu) kadar, faktöriyel sayı sistemi endeksi ifade ve orijinal diziden bir seçim olarak basamak kullanımı (Değiştirmeden).

+3

https://secure.wikimedia.org/wikipedia/en/wiki/Combinatorial_number_system#Ordering_combinations Bu daha fazla yardımcı olmaz mıydı? –

+0

Evet. Ben bir aptalım. Kombinasyonlardan ziyade permütasyon olarak okudum. Aralarında basit bir haritalama olabilir, bir dizi N elemanından alınan k elemanlarının jth kombinasyonu gibi bir şey, j (k!) (Nk!) 'Nin permütasyonunun ilk k elemanları ile aynıdır. N elementi ama belki de değil. –

0

Ben senin sorunun altında düşmeye görünen sorunun türüdür binom katsayısı, çalışmaya yönelik ortak fonksiyonları işlemek için bir sınıf yazdım. Herhangi N bir dosyaya K seçmek için güzel biçimde

  1. Çıkışlar tüm K-dizinleri: Aşağıdaki görevleri yerine getirir. K-indeksleri daha açıklayıcı dizeler veya harfler ile ikame edilebilir. Bu yöntem, bu tür problemleri çözmeyi oldukça önemsiz kılmaktadır.

  2. K-dizinlerini, sıralı binom katsayısı tablosundaki bir girişin uygun dizinine dönüştürür. Bu teknik, yinelemeye dayanan eski yayınlanmış tekniklerden çok daha hızlıdır. Bunu Pascal'ın Üçgen'inde bulunan matematiksel bir özelliği kullanarak yapar. Makalem bundan bahsediyor.Ben keşfetmek ve bu tekniği yayınlayan ilk olduğuma inanıyorum, ama yanlış olabilir.

  3. karşılık gelen K-endekslere sıralanmış bir binom katsayısı tablosundaki dizin dönüştürür. Ayrıca yayınlanmış diğer tekniklerden daha hızlı olduğuna inanıyorum.

  4. Taşma işleminin çok daha az olası olduğu ve daha büyük sayılarla çalıştığı binom katsayısını hesaplamak için kullanır.

  5. sınıf NET C# ile yazılmış ve bir genel liste kullanarak sorunun (varsa) ilgili nesneleri yönetmek için bir yol sağlar. Bu sınıfın yapıcı yönetilecek nesneleri tutmak için genel bir liste oluşturmak zaman bu doğru InitTable adında bool değeri alır. Bu değer yanlışsa, tablo oluşturmaz. Yukarıdaki 4 yöntemi yerine getirmek için tablonun oluşturulmasına gerek yoktur. Tabloya erişmek için erişim yöntemleri sağlanmıştır.

  6. sınıfı ve yöntemleri nasıl kullanılacağını gösterir bir ilgili test sınıfı vardır. 2 vaka ile kapsamlı bir şekilde test edilmiştir ve bilinen bir hata yoktur.

bu sınıfa hakkında okumak ve kodunu indirmek Tablizing The Binomial Coeffieicent görmek için.

Bu sınıfı Java, Python veya C++'ye dönüştürmek zor olmamalıdır.

İlgili konular