O (n) zamanda: Karşılaştırmanın geçişli olmadığı kümedeki en büyük elemanı bulun


21

Başlık soruyu belirtir.

Girdiler olarak karşılaştırabileceğimiz (hangisinin en büyük olduğunu belirleyebileceğimiz ) bir öğe listesine sahibiz . Hiçbir öğe eşit olamaz.

Anahtar noktaları:

  1. Karşılaştırma geçişli değildir (taş kağıt makasını düşünün): bu doğru olabilir: A> B, B> C, C> A (burada geçerli bir cevap olmadığından bunun geçerli bir girdi olmadığını unutmayın, sadece ne olduğunu açıklıyorum " geçişsiz karşılaştırma "anlamına gelir)
  2. Her giriş dizisinin bir cevabı olacaktır
  3. en büyük , öğenin diğer tüm öğelerden daha büyük olması gerektiği anlamına gelir
  4. Converse özelliği, yani A> B'nin B <A

Örnek:

Input: [A,B,C,D]
A > B, B > C, C > A
D > A, D > B, D > C
Output: D

Bunu O (n) zamanda yapmanın bir yolunu bulamıyorum, en iyi çözümüm O (n ^ 2).

Bir yanıttan emin olmak için, öğenin gerçekten cevap olduğunu kanıtlamak için öğenin açıkça diğer tüm öğelerle karşılaştırılması gerektiği için her yaklaşıma takılı kalıyorum (karşılaştırma karşılaştırmalı değildir).

Bu, bir yığın, sıralama vb.


8
"En büyük element" in nasıl tanımlanacağı belirsiz mi? Örneğin, ise hangi eleman en büyüktür ? Başka karşılaştırma kurallarınız var mı? A>B,B>C,C>bir
fade2black

6
En azından kısmen sipariş edilmemiş bir setteki en büyük elementi nasıl seçeceğimizi hayal edemiyorum. Lütfen en büyük ve en küçük öğenin tanımına bakın . Geçişsizlik eksikliği, kısmi sıralamayı dışlar.
fade2black

3
@ fade2black Beni neden "en büyük" tanımına bağlıyorsunuz? Açıkça bu sorunun bağlamı için en büyük tanımını belirtiyorum. En büyük anlamı, eleman diğer elemanlardan daha büyüktür. Hiçbir öğe eşit değildir. Hepsi bu kadar. Bu belli değil mi?
James Wierzba

2
A, B, C, D ile son örneğiniz, OP'nize eklediyseniz sorunuzu anlamanıza yardımcı olacaktır.
fade2black

3
C # derleyici ekibinin bir üyesi bunu bir röportaj sorusu olarak soruyordu; bu önemlidir, çünkü C # 'da, aşırı yük çözünürlüğü algoritması genellikle bir "betterness" ilişkisi göz önüne alındığında bir kümenin benzersiz en iyi üyesini seçmelidir, ancak mutlaka geçişli değildir. (Ya da böyle eşsiz bir en iyi üye yoksa uygun bir yanıt verin; bağlar mümkündür.) Doğru cevap verebilmeme rağmen, bunun özellikle iyi bir görüşme sorusu olduğunu düşünmedim çünkü doğrusal algoritma.
Eric Lippert

Yanıtlar:


38

Maksimum değeri bulmak için standart algoritma hala çalışır. İle başlayın ve daha büyük bir değer görürseniz, elemanlar üzerinden gitmek, bu değerin ne olmasını maksimum güncelleyin. Bunun nedeni, atladığınız her öğenin en az bir öğeden daha küçük olması ve dolayısıyla maksimum olamaz.a1

Açık olmak gerekirse, "standart algoritma" ile aşağıdakileri kastediyorum:

max <- a_1
for i=2 to n
   if a_i > max
      max <- a_i
output max

Tamlık için, burada yorumlarda ortaya çıkan sorunları tartışacağım. Yukarıdaki tartışmada ayar bir anti simetrik ilişkisi maksimum göreli buluyor , bir i herkes için eğer bir maksimum j i Elimizdeki bir i > bir j . Yukarıdaki algoritma, bir maksimumun var olduğu varsayımı altında çalışır, ancak bu bilinmiyorsa, bir maksimumun varlığını doğrulamak için kullanılabilir (döndürülen öğenin gerçekten diğer tüm öğelerden daha büyük olup olmadığını kontrol edin, bu Chi'nin yorumunda belirtilmiştir ve Ilmari Karonen cevabında).<aijiai>aj

Eğer mutlaka karşı simetrik olmayan (Emil açıklamalarda belirtildiği gibi), o zaman yukarıda algoritma başarısız olur. Eğer < keyfi bir ilişkiyse (yani hem transitiviteyi hem de anti simetriyi rahatlatıyoruz), o zaman lineer zamanda maksimum bulmanın mümkün olmadığını göstermek zor değildir. Tarafından Göstermek # bir i kaç kez bir i bir sorguya katılan, biz maksimum yeterince sorgular olmadan ortaya olamaz bir şekilde düşmanca bir ilişki tanımlar. Sorgu Verilen bir i > ? a j , cevap a i > a j eğer # a i<<#aiaiai>?ajai>ajAksi halde < n - 1 ve a i < a j . Sorgu sayısı o ( n 2 ) ise , henüz bir maksimum görülmedi ve kümedeki öğelerden biri olacak şekilde ayarlanabilir.#ai<n1ai<ajo(n2)


1
@JamesWierzba (sanırım) o sadece "atlanmış" bir elementin şu anki maks. Standart algoritmayı göz önünde bulundurun: listenizdeki her bir değeri geçerli maksimum değerle karşılaştırırsınız. Her listede büyük bir unsur olduğunu söylediniz. Bir noktada, bunu mevcut maksimum değerinizle karşılaştıracaksınız ve daha büyük olduğu için bu değer yeni maksimum değeriniz olur. Bu değer listedeki her şeyden daha büyük olduğundan, asla daha büyük bir öğe bulamazsınız ve en büyük değeriniz değiştirilmez. nKarşılaştırmalardan sonra , şu anki maks. Yanıtınız olmalı
Lord Farquaad

1
Anlaşılır olması için düzenlenmiş olan bu algoritma geçiş gerektirmez. Buna inanmakta zorlanıyorsanız, doğruluk kanıtı ayrıntılarını izleyin (çelişki amacıyla, döndürülen değerin maksimum olmadığını varsayalım ve ilk paragraftaki fikri kullanın).
Ariel

7
Bu, şu sorudaki varsayım 2'ye dayanmaktadır: dizide her zaman bir maksimum vardır. Eğer durum böyle değilse, maxsadece bir alt dizinin maksimum değeri olabilir. Yine de, varsayım 2 olmadan bile, bir belirsiz maksimum bulunabilir ve daha sonra O (n) bağlı ikinci bir tarama kullanarak tüm dizi üzerinde doğrulanabilir.
chi

7
Bu cevap ve B > A'nın aynı anda tutamayacağını varsayar . Görebildiğim kadarıyla, bu soruda göz ardı edilmedi. A>BB>A
Emil Jeřábek, Monica

4
@ oconnor0 Bunu takip etmiyor. Somut bir örnek için A> B, A> C, B> A ve C> B'yi varsayalım. A, kümedeki diğer tüm öğelerden daha büyüktür (ve bu özelliğe sahip tek öğedir), ancak öğeler A, B, C düzeninde karşılaşılan algoritma C çıktısını alır.
Emil Jeřábek Monica

24

Ariel'in belirttiği gibi , aşağıda verilen standart maksimum bulma algoritması:

def find_maximum(a):
    m = a[0]
    for x in a:
        if x > m: m = x
    return m

Aslında şu sürece değişiklik yapmadan çalışacaktır:

  • herhangi bir eleman çifti karşılaştırılabilir ve
  • girişin maksimum bir öğe içerdiği garanti edilir, yani girişteki diğer tüm öğelerden çift olarak daha büyük bir öğe.

(Yukarıdaki ilk varsayım, maksimum öğenin diğer x > ytüm öğelerle karşılaştırılabilir olduğunu ve öğeler xve ykarşılaştırılamazsa her zaman yanlış olduğunu varsaydığımız sürece, algoritmayı değiştirmek zorunda kalmadan bile gerçekten rahatlatılabilir .)

Özellikle:

[…] Bir yanıttan emin olmak için, öğenin açıkça diğer tüm öğelerle karşılaştırılması gerekir (çünkü karşılaştırma geçişli değildir).

yukarıda verilen varsayımlar altında doğru değildir. Aslında, yukarıdaki algoritmanın her zaman maksimum unsuru bulacağını kanıtlamak için şunları gözlemlemek yeterlidir:

  1. döngü tüm girdi öğeleri üzerinde yinelendiği için, bazı yinelemelerde xmaksimum öğe olacaktır;
  2. maksimal eleman diğer tüm elemanlardan çift olarak büyük olduğu için, bu yinelemenin sonunda mmaksimum eleman olacağını takip eder; ve
  3. başka hiçbir öğe maksimum öğeden çift olarak daha büyük olamayacağından m, sonraki yinelemelerde değişmeyecektir.

Bu nedenle, döngünün sonunda m, giriş bir tane içeriyorsa , her zaman maksimum öğe olacaktır.


Ps. Giriş yoksa değil mutlaka her zaman maksimal eleman içerirler, o zaman gerçekten maksimal olduğunu doğrulamak için her elemana karşı aday cevabı test gerektiren aslında gerçeğini doğrulayan. Bununla birlikte, yukarıdaki maksimum bulma algoritmasını çalıştırdıktan sonra yine de O ( n ) zamanda yapabiliriz :

def find_maximum_if_any(a):
    # step 1: find the maximum, if one exists
    m = a[0]
    for x in a:
        if x > m: m = x

    # step 2: verify that the element we found is indeed maximal
    for x in a:
        if x > m: return None  # the input contains no maximal element
    return m  # yes, m is a maximal element

(Burada ilişkinin >düzensiz olduğunu varsayıyorum, yani hiçbir öğe kendisinden daha büyük olamaz. Durum böyle değilse x > m, adım 2'deki karşılaştırmanın yerine geçmesi gerekir x ≠ m and x > m, burada kimlik karşılaştırmasını gösterir. Ya da sadece optimizasyonu uygulayabiliriz Aşağıda belirtilmiştir.)

Algoritmanın bu varyasyonunun doğruluğunu kanıtlamak için iki olası durumu göz önünde bulundurun:

  • Giriş maksimum bir öğe içeriyorsa, 1. adım onu ​​(yukarıda gösterildiği gibi) bulur ve 2. adım bunu onaylar.
  • Giriş yoksa değil bir maksimal elemanı ihtiva ardından 1. adımı gibi bazı keyfi elemanı çekme sona erecek m. Hangi eleman olduğu önemli değil, çünkü her durumda maksimal olmayacak ve bu nedenle 2. adım bunu tespit edip geri dönecek None.

Biz dizinini depolanmış olursa mgirdi dizisinde a, biz aslında sadece önce gelen unsurları kontrol etmek optimize 2. adımı olabilir mde adaha sonraki unsurların beri, zaten karşılaştırılmıştır m1. adımda Ama bu optimizasyon asimptotik zaman karmaşıklığı değişmez algoritma, ki bu hala O ( n ) 'dir.


3
Aslında OP birçok ayrıntıyı atlıyor. Örneğin, ilişkinin refleksivitesi hakkında hiçbir şey söylenmez ve bu nedenle refleksif değilse if x > m:tanımsızdır.
fade2black

4

O(n)

Listenizi karşılaştıran öğeleri gözden geçirirseniz, bir karşılaştırmayı "kaybeden" herhangi bir öğe, en büyük olması için TÜM diğer öğelerden daha büyük olması gerektiği için hemen atılabilir, böylece tek kayıp onu diskalifiye eder.

n1

Bu çözüm bir incelik tarafından etkinleştirilir: "Hiçbir öğe eşit olamaz", her zaman en büyük öğe olacağı gerçeğiyle birleştiğinde. Kazançları yönlendirilmiş bir grafik olarak eşlersek, kazanmaları takip ederek en büyük elemente ulaşabileceğimiz açıktır.


1
" Asiklik yönlendirilmiş grafik " yanlış modeldir: bunun yerine " turnuva " olmalıdır. Döngülere izin verilir ve her kenarın tam olarak bir yönde olması çok önemlidir.
Peter Taylor

@PeterTaylor kesinlikle haklısın, sadece 'en büyük' ​​öğeye giden kazançları düşünüyordum, diğer kazançlar daha az alakalı, ancak en iyisini keşfetme yolunda ilerleyebilirler, böylece haklısın ' t indirimli
Danikov

3

En azından tek bir eleman için antisimetrik ilişkinin (en büyük elemanın varlığını garanti eden) varsayıyorum, aksi takdirde görev imkansızdır. Sonlu kümedeki tüm elemanlar karşılaştırılabilir ise, normal bulma-maksimum prosedürü çalışır.

Bazı elemanlar karşılaştırılamazsa, aşağıdaki prosedür işe yarayacaktır

max = nil
For i=1 to n
   if max is nil then
      max = a[i]
   if max and a[i] are not comparable then
      max = nil
   else if max < a[i] then
      max = a[i]
End

bir,B,C,D

bir>B,B>C,C>bir
D>bir,D>B,D>C


ben=1: maksimum=bir
ben=2: maksimum=birbir>B
ben=3: maksimum=Cbir<C
ben=4: maksimum=DD>C

m>birbir<mbirmm<birbirmbirm


İlkinin else ifgerekli olduğunu düşünmüyorum . maxMaksimum ise tetiklenir ve maksimum değere henüz ulaşılmadıysa, değerinin ne olduğu önemli değildir max.
rici

Evet, bu birincisi. Diğeri ikinci olan :)
rici

Yani ifs olmadan ayrılmak elsemı? Bu sadece bir alışkanlık: elses ile kıyaslamıyoruz bile. :)
fade2black

1
maxListenin herhangi bir öğesine başlamak ve döngü içinde başlatmak daha kolay olmaz mıydı if max and a[i] are comparable and max < a[i] then max = a[i]?
Ilmari Karonen

1
@badallen OP her zaman en büyük unsurun olduğunu varsayar. Örneğinizde en büyük unsur yoktur.
fade2black

2

bir<BB<bir

bir1...birnbirben<birj

n2

birben<birjj

j0birben<birj0benjbenjbirben<birjbenbenjbirbenj<birjj0benj

Umarım bu biraz anlaşılabilir. Yorumlarınızı sormaktan veya düzenlemekten çekinmeyin.

Temel fikir, tamamen keyfi bir ilişkiye izin veriyorsanız, zaten bildiğiniz olanlardan kalan öğeler hakkında herhangi bir bilgi toplayamayacağınızdır.

bir<birnn2-n


1

A > Bn

Bu şekilde, yalnızca girdiler arasında geçiş yapabilir ve olası çözüm kümesinden diğerinden daha az olan öğeyi kaldırabilirsiniz. Bir hashset veya benzeri ile bu de mümkündürO(n)

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.