İki büyük küme arasındaki küme farkını hesaplama


14

İki büyük A ve tamsayı kümem var B. Her kümede yaklaşık bir milyon giriş vardır ve her giriş en fazla 10 basamak uzunluğunda pozitif bir tamsayıdır.

AB ve hesaplamak için en iyi algoritma nedir BA? Başka bir deyişle, A olmayan ve olmayan girişlerin listesini nasıl verimli bir şekilde hesaplayabilirim B? Bu operasyonları verimli hale getirmek için bu iki seti temsil eden en iyi veri yapısı ne olabilir?

Gelebileceğim en iyi yaklaşım, bu iki seti sıralı listeler olarak saklamak ve A her elemanını her elemanıyla Bdoğrusal bir şekilde karşılaştırmaktır. Daha iyisini yapabilir miyiz?


Farklı bir şekilde saklamak istiyorsanız, daha iyi sonuçlar alabilirsiniz.
Realz Lahana Salatası

Ayrıca, sonuçları örtük bir veri yapısı olarak almak istiyorsanız; sadece kendi setlerinin her birine cevap vermek için iki seti sorgulayan bir yapı oluşturabilirsiniz.
Realz Lahana Salatası

1
@ user917279 Büyük bir nokta: genellikle ön işleme / yapım süresi, sorgu süresi ve bellek kullanımını birbirinize göre değiştirebilirsiniz. Yapıyı nadiren düzenliyor, ancak çok mu sorguluyorsunuz? Tam tersi? Bellek endişe mi ediyor? Bu tür sorular pratik bir bakış açısıyla cevaplanabilir ve "doğru" "teorik" yapının seçimine bilgi verebilir.
Raphael

1
@Raphael Daha fazla bellek kullanarak ve / veya hazırlık için daha fazla zaman harcayarak birleşik olarak kalıcı setlerden (karmaşıklık açısından) daha iyisini yapabileceğinizi düşünüyor musunuz? Mümkün olup olmadığını düşünüyorsanız merak ediyorum. Arama tablolarını bu boyuttaki girdi kümeleri için bir seçenek olarak görmüyorum.
smossen

1
@ user917279 Aynı iki dev küme örneğini göz önünde bulundurursanız, karma-consing kullanılarak oluşturulan herhangi bir veri yapısı, eşit yapılar oluşturulduğunda birleştirilecek ve böylece aynı bellek konumunu paylaşacağından O (1) 'de eşitlik testini destekleyecektir. Konfluent olarak kalıcı setler, iki yapı neredeyse eşit olduğunda da has-consing'ten yararlanır. Karmaşıklık, şimdiye kadar sipariş edilen setler için gördüğüm en iyisidir.
smossen

Yanıtlar:


9

Kümeleri özel bir veri yapısında saklamak istiyorsanız, muhtemelen bazı ilginç karmaşıklıklar elde edebilirsiniz.

I=O(min(|A|,|B|,|AΔB|))

Daha sonra , her biri ve beklenen süre. Yani esasen, hangisinin daha az olursa olsun, iki setin minimum boyutunu veya simetrik farkın boyutunu elde edersiniz. Simetrik fark küçükse bu doğrusaldan daha iyidir; yani. eğer büyük bir kavşakları varsa. Aslında, istediğiniz iki set farkı işlemi için, bu pratik olarak çıktıya duyarlıdır, çünkü birlikte simetrik farkın boyutunu oluştururlar.A Δ B O ( I log | A | + | B |AB,AB,ABAΔBO(Ilog|A|+|B|I)

Daha fazla bilgi için bkz. Olle Liljenzin (2013) tarafından Kesintisiz Kalıcı Kümeler ve Haritalar .


Makaledeki ardı sıraları arama ağaçlarıdır. Bunları sıralanmamış veri yapıları olarak saymazdım.
smossen

@smossen yeterince doğru, bunu düzenledim.
Realz Slaw

6

Kümeler sıralanmış bağlantılı listeler olarak temsil edilirse, doğrusal tarama nasıl yapılacağını bildiğim en iyisidir. Çalışma süresi .O(|A|+|B|)

her bir öğesini her bir öğesiyle karşılaştırmanız gerekmediğini unutmayın . Bu , daha kötü olan çalışma süresine yol açacaktır . Bunun yerine, bu iki kümenin simetrik farkını hesaplamak için, her iki kümede ortak olan değerleri atlamak için uygun şekilde değiştirilmiş, mergesort'taki "birleştirme" işlemine benzer bir teknik kullanabilirsiniz.B O ( | A | × | B | )ABO(|A|×|B|)

Daha ayrıntılı olarak, hesaplamak için aşağıdakine benzer bir özyinelemeli algoritma ; ve değerleri sıralanmış düzende bağlantılı listeler olarak gösterildiği varsayılır :A BABAB

difference(A, B):
    if len(B)=0:
        return A # return the leftover list
    if len(A)=0:
        return B # return the leftover list
    if A[0] < B[0]:
        return [A[0]] + difference(A[1:], B)
    elsif A[0] = B[0]:
        return difference(A[1:], B[1:])  # omit the common element
    else:
        return [B[0]] + difference(A, B[1:])

Bunu sahte Python'da temsil ettim. Python okumak yoksa, A[0]bağlantılı liste başıdır A, A[1:]listenin geri kalanı ve +listelerin birleştirme temsil eder. Verimlilik nedeniyle, Python'da çalışıyorsanız, muhtemelen tam olarak yukarıdaki gibi uygulamak istemezsiniz - örneğin, birçok geçici liste oluşturmaktan kaçınmak için jeneratörleri kullanmak daha iyi olabilir - ancak fikirleri mümkün olan en basit biçimde gösterir. Bu sahte kodun amacı sadece somut bir uygulama önermemek değil, algoritmayı açıklamaktır.

Kümeleriniz sıralı listeler olarak gösteriliyorsa ve çıktının sıralı bir liste olarak sunulmasını istiyorsanız, daha iyisini yapmanın mümkün olduğunu düşünmüyorum. Temel olarak ve her elementine bakmak zorundasınız . Gerekçe Gayri kroki: Eğer bakmadım dair herhangi bir unsur varsa, yapamazsın çıktı o, bunu hem mevcut olduğunu biliyorum eğer bir unsuru bakarak atlayabilirsiniz tek durum yani ve , ama değerine bakmadıysanız bunun mevcut olduğunu nasıl bilebilirsiniz?B A BABAB


fantastik, kümelerin sıralı listeler olarak saklanacağı kısıtlaması kaldırılırsa başka seçeneklerimiz var mı?
user917279

2

A ve B eşit büyüklükte, ayrık ve serpiştirilmişse (örneğin A'daki tek sayılar ve B'deki çift sayılar), o zaman öğelerin doğrusal zamandaki çift karşılaştırması muhtemelen en uygunudur.

A ve B, tam olarak A veya B'den birinde veya her ikisinde bulunan öğe blokları içeriyorsa, alt lineer zamanda küme farkı, birleşim ve kesişimin hesaplanması mümkündür. Örnek olarak, A ve B tam olarak bir maddede farklılık gösteriyorsa, fark O (log n) olarak hesaplanabilir.

http://arxiv.org/abs/1301.3388


1
Setlerin sıralandığını, yani listeler, arama ağaçları veya başka bir şey olarak saklandıkları anlamına gelebilir. Verilerin liste olarak depolanması gerekiyorsa, hiçbir algoritmanın listeleri doğrusal zamanda (zaten bir algoritma bulduğu) taramaktan daha iyisini yapamaması durumunda "AB'yi hesaplamak için en iyi algoritmayı" istemek oldukça ilginçtir.
smossen

1
Tanrım, aynı kağıt bağlantılı olarak (Ben, aynı sen, daha doğrusu gibi) ... bağlantılarınızı sefere isim: D
Realz Slaw

@smossen fantastik, sahip olduğum bilgi (?) ne olursa olsun, onları sıralanmış listeler olarak temsil ettim, ama diğer önerileri de alçakgönüllülükle karşılarım.
user917279

2

bir seçenek, ( konumun bir öğenin varlığını veya yokluğunu temsil ettiği) ve set tipi işlemleri temsil etmek için bitvektörleri kullanmak ve daha sonra dijital bilgisayarlarda hızlı bir şekilde (ve paralel olarak birden fazla bitte) gerçekleştirilebilen ikili işlemlere indirmektir. . bu durumda = burada bitvektörlerdir. bu tekniğin diğer tekniklere göre nispi etkinliği de seyrekliğe bağlıdır. daha yoğun kümeler için diğer yaklaşımlardan daha verimli olabilir. ayrıca elbette tüm operasyon utanç verici bir şekilde paraleldir, böylece ayarlanan işlemler paralel olarak yapılabilir.A - B a ¯ b a , bnABab¯a,b


İle Olası girişlerin, vektörler tüm pratik de değildir ısırdı. 1010
Raphael

1
R., konuyu özlüyor. tek bir long32 eleman veya 1 byte, 8 eleman depolayabilir . böylece 1M girişleri sadece ~ 125K RAM'de saklanabilir! depolama, sorunun nasıl uygulandığına bağlı olarak diğer gösterimlerden önemli ölçüde daha verimli olabilir ...
vzn

Bu yüzden OP'nin ilgilendiği setler için 12MB'ın üzerine ihtiyacınız olacak. Bu, tüm önbellekleri (şu anda) esiyor ve seyrek setler için korkunç olacak. Özellikle, boş bir küme oluşturmak diğer tüm işlemlere hükmeder (seyrek kümeler için). Knuth bu sorunu TAoCP'de ele alıyor.
Raphael

12MB? ha? poster sadece 2 takım olduğunu söyledi. poster setinin seyrekliğini / yoğunluğunu belirtmedi. bu benim cevabımda belirtiliyor. Seyrek setlere sahip olduğunu mu düşünüyorsun? Doğru Bir Yanıt yoktur, yaklaşım koşullara bağlı olarak yararlı olabilecek alternatif bir seçenek olarak belirtilir . bu bağlamda nadiren kullanılmaz ...
vzn

Soruyu yeniden okumanızı öneririm: "Her kümede yaklaşık bir milyon giriş vardır ve her giriş en fazla 10 basamak uzunluğunda pozitif bir tamsayıdır." Orada oluşabilir farklı numaralar ve yaklaşık vardır listedeki olanlar. Bu, bit vektörünüzdeki tüm girişlerin sadece% 0,01'inin 1 olduğu anlamına gelir - buna çok seyrek diyebilirim. (12MB'ımın çok düşük olduğu anlaşılıyor; elbette .) 10 6 10 10 b1,15 G B10101061010b1.15GB
Raphael
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.