zamanında üç boyutlu sıralı dizileri bulan bir algoritma var mı ?


21

tamsayı dizisi A verildiğinde , i , j ve k olmak üzere üç indeks bulan , i < j < k ve A [ i ] < A [ j ] < A [ k ] olduğunu kanıtlamak veya çürütmek istiyorum. (veya böyle bir üçlü olmadığını bulur) doğrusal zamanda.Ai,jki<j<kA[i]<A[j]<A[k]

Bu bir ödev sorusu değil; Bunu “böyle bir algoritmayı uygulamaya çalışın” şeklinde bir programlama forumunda gördüm. Çeşitli deneylerden sonra bunun imkansız olduğundan şüpheleniyorum. Sezgim bana öyle söylüyor, ama bu gerçekten hiçbir şey için geçerli değil.

Resmi olarak kanıtlamak istiyorum. Bunu nasıl yapıyorsun? İdeal olarak adım adım ortaya konmuş bir kanıt görmek isterim ve o zaman bu kadar eğimliyseniz, genel olarak bu gibi basit soruları kanıtlama / çürütme konusunda nasıl bir açıklama yapacağım. Yardımcı olursa, bazı örnekler:

[1,5,2,0,3] → (1,2,3)
[5,6,1,2,3] → (1,2,3)
[1,5,2,3] → (1,2,3)
[5,6,1,2,7] → (1,2,7)
[5,6,1,2,7,8] → (1,2,7)
[1,2,999,3] → (1,2,999)
[999,1,2,3] → (1,2,3)
[11,12,8,9,5,6,3,4,1,2,3] → (1,2,3)
[1,5,2,0,-5,-2,-1] → (-5,-2,-1)

Biri üzerinde yinelenebilir ve her seferinde bir i < j (bizim mevcut j , yani), yeni bir üçlü yapmak ve bir dizi üzerine itmek gerekiyordu. Üç katımızdan biri tamamlanana kadar her üç katına çıkmaya ve karşılaştırmaya devam ediyoruz. Bu tıpkı Yani , ! Ama üçlü dizimizdeki üçlü sayısı en kötü durumda giriş listesinin boyutuna karşılık geleceğinden, bu sadece O ( n ) ' den daha karmaşık olduğunu düşünüyorum .Ai<jj[1,5,2,0,-5,-2,-1] → 1..2.. -5.. -2.. -1[1,5,2,0,-5,-2,3,-1] → 1..2.. -5.. -2.. 3O(n)



Not kötü durumda (sıralı dizi) içinde bile olduğunu birçok uygun triple. Lütfen yalancı kod olarak önerdiğiniz algoritmayı vermeyi düşünün; Bence açıklamanız tamamlanmadı. Θ(n3)
Raphael

Yanıtlar:


14

Bu, En Uzun artan alt sekil probleminin varyasyonudur ; bu, ve P iki yardımcı dizisi kullanılarak Wikipedia'da sunulan çözümdür :MP

  • -en küçük A [ k ] değerinin k konumunu, k i aralığında A [ k ] ilebiten j uzunluğunun artan biralt sekansı olacak şekildesaklar(burada j k i var, çünkü j artan alt sekansın uzunluğunu ve k sonlandırma pozisyonunu temsil eder Açıkçası, 11 pozisyonunda biten 13 uzunluğundaki artan bir sekansa asla sahip olamayız.M[j]kA[k]jA[k]kijkijk1311. tanım gereği).ki
  • - mağaza selefi pozisyonu A [ k ] biten en uzun artan altdizi içinde A [ k ] .P[k]A[k]A[k]

    Ek olarak algoritma , şimdiye kadar bulunan en uzun artan alt sekansın uzunluğunu temsil eden bir değişken depolar .L

Bu algoritma en kötü durumda çalışır . Senin sorunun dönmeye izin veren özel bir durum olduğunda L = 3 iter aşağı çalışma zamanı O ( n ) ikili arama süresi içinde nedenle, hangi iki en az uzunlukta diziler sadece çalışır çünkü O ( 1 ) karşıt olarak Θ ( log n ) genel durumda.Θ(nlogn)L=3O(n)O(1)Θ(logn)

Değiştirilmiş sözde kodu düşünün:

 L = 0
 for i = 1, 2, ... n:
    binary search for the largest positive j ≤ L
      such that X[M[j]] < X[i] (or set j = 0 if no such value exists)
    P[i] = M[j]
    if j == L or X[i] < X[M[j+1]]:
       M[j+1] = i
       L = max(L, j+1)
   if L==3 : return true; // you can break here, and return true.
return false; // because L is smaller than 3.

@SaeedAmiri Ben yorum gördüm ama henüz gözden geçirmek için zaman yoktu (yatağa gitmeden önce soru yayınladı). Bağlantınızdan L = 3 özel durumumuzun bir şekilde yardımcı olacağından şüphelendim, ancak ayrıntıları anlama şansı yoktu. Şu anda işteyim ve zamanım kısıtlı. Cevabınızı takdir ettiğimden emin olun. İçindeki her satırı tam olarak anlamadan size teşekkür etmek benim için yüzeysel olur.
Christopher Bitti

@SaeedAmiri: Burada daha fazla "boşluk doldurma" beklediğinizi kabul ediyorum, ancak yine de en azından bir kanıtın (ancak kabataslak) köşe argümanlarını vermek zorundasınız. OP ile ilgili olarak, İtalya'da olduğu görülüyor, bu yüzden muhtemelen yorumunuz ve cevabınız arasında hızlı uyuyordu (ve olasılıkla şimdi doğu ile meşgul olma ihtimali var).
Raphael

@ChristopherDone, seni üzmek istemiyorum, üzgünüm bu benim hatam, kesinlikle haklısın.

+1: Bu güzelleşir, sadece bir geçiş yapar ve alanıdır. O(1)
Aryabhata

Tamam, iyi görünüyor. En uzun artan sekans algoritmasının davranışını incelemek biraz zamanımı aldı. Bundan sonra, maksimum uzunluk == 3 değişikliği iyidir. Teşekkürler!
Christopher

11

Metodoloji üzerine bir not

Bu sorun hakkında biraz düşündüm ve bir çözüm buldum. Saeed Amiri'nin cevabını okuduğumda , bulduğum şeyin uzunluk 3 dizisi için standart en uzun takip bulma algoritmasının özel bir versiyonu olduğunu fark ettim, çünkü çözümü bulduğum yolu gönderiyorum, ilginç bir problem çözme örneğidir.

İki elemanlı versiyon

i<jA[i]<A[j]

Ai<j,A[i]A[j]i,A[i]A[i+1]iA[i]<A[i+1]

Bu dava çok basit; genellemeye çalışacağız. Belirtildiği gibi sorunun çözülemediğini gösterir: istenen endeksler her zaman mevcut değildir. Dolayısıyla, algoritmanın ya varsa, geçerli indeksleri döndürmesini ya da böyle bir indeksin olmadığını doğru bir şekilde iddia etmesini tercih edeceğiz.

Algoritma ile geliyor

A(A[i1],,A[im])i1<<imA(A[i],A[i+1],,A[i+m1])

Az önce talep edilen endekslerin her zaman mevcut olmadığını gördük. Stratejimiz, endeksler olmadığında çalışmak olacaktır. Bunu, endeksleri bulmaya çalıştığımızı varsayarak ve aramamızın nasıl yanlış gidebileceğini görerek varsayalım. Daha sonra aramanın yanlış gitmediği durumlar, endeksleri bulmak için bir algoritma sağlayacaktır.

4,3,2,1,0

j=i+1k=j+1A[i]<A[i+1]<A[i+2]

4,3,2,1,2,3,2,1,0

A[j]<A[j+1]iA[i]<A[j]kA[j+1]<A[k]

4,3,2,2.5,1.5,0.5,1,0

ik

3,2,1,3.5,2.5,1.5,0.5, -0.5,1.25, -0.25 3,2,1,2.5,1.5,0.5,2,1,0

ijki

2.1,3,2,1,2.5,1.5,0.5,2,1,0 1,2,0,2.5,1.5,0.5

i(i,j)ki(i,j)(i,j)i>jA[i]<A[i]ii(i,j)jA[j]<A[j](i,j)

Algoritmanın ifadesi

Python sözdiziminde verildi, ancak test etmediğime dikkat edin.

def subsequence3(A):
    """Return the indices of a subsequence of length 3, or None if there is none."""
    index1 = None; value1 = None
    index2 = None; value2 = None
    for i in range(0,len(A)):
        if index1 == None or A[i] < value1:
            index1 = i; value1 = A[i]
        else if A[i] == value1: pass
        else if index2 == None:
            index2 = (index1, i); value2 = (value1, A[i])
        else if A[i] < value2[1]:
            index2[1] = i; value2[1] = A[i]
        else if A[i] > value2[1]:
            return (index2[0], index2[1], i)
    return None

İspat taslağı

index1dizinin daha önce geçirilmiş olan bölümünün minimum sayısının dizinidir (birkaç kez gerçekleşirse, ilk oluşumu koruruz) veya Noneilk öğeyi işlemeden önce. index2uzunluk 2'nin artan diziliminin indekslerini, dizinin zaten en büyük öğeye sahip olan zaten geçirilmiş kısmında veya Noneböyle bir dizi mevcut değilse saklar .

Ne zaman return (index2[0], index2[1], i)çalışır, biz value2[0] < value[1](bu değişmez olduğu value2ve) value[1] < A[i](bağlamdan bellidir). Döngü, erken dönüşü başlatmadan sona ererse value1 == None, bu durumda, yalnız başına 3 uzunluğunda 2 artan sırası yoktur veya value1en düşük en büyük elemana sahip 2 numaralı artan alt sırası içerir. İkinci durumda, ayrıca, 3 uzunluğunda artan bir artışın bundan daha önce bitmediği değişmezimiz vardır value1; bu nedenle, bu tür bir alt sekansın son unsuru, value23 uzunluğunun artan bir alt sekansını oluşturacaktır: ayrıca value2dizinin zaten çaprazlanmış bölümünde yer alan 3 uzunluğunun artan bir alt sekansının bir parçası olmayan değişmezimiz olduğu için, dizinin tamamında böyle bir sıra yoktur.

Yukarıda adı geçen değişmezleri kanıtlamak okuyucu için bir egzersiz olarak bırakılmıştır.

karmaşa

O(1)O(1)O(n)

Resmi kanıt

Okuyucuya bir egzersiz olarak bırakıldı.


8

O(n)O(n)

İlk olarak, bir yığını ve her bir öğe için, ondan daha büyük bir öğenin dizinini ve sağını gösteren bir yardımcı diziyi koruyarak soldan sağa doğru ilerleyin.

1

Dizideki yeni bir öğeyi her düşündüğünüzde, bu öğe yığının üst öğesinden büyükse, yığının dışına çıkar ve yeni öğenin dizinini üste karşılık gelen aux dizi öğesini ayarlarsınız. dikkate.

Geçerli öğe daha büyükken öğeleri yığının dışına atmaya ve karşılık gelen dizini ayarlamaya devam edin. Üst kısım daha az olmayan (veya boş olan) bir öğeye sahip olduğunda, geçerli öğeyi yığının üzerine itin ve yukarıdaki adımı tekrarlayarak dizinin bir sonraki öğesine ilerleyin.

Başka bir geçiş (ve başka bir aux dizisi) yapın, ancak sağdan sola gidin.

1

O(n)

ki

İlk geçiş için sözde kod şöyle görünebilir:

Stack <Pair<Elem, Index>> greats;
Elem auxArr[inputArr.Length];

for (Index i = 0; i < inputArr.Length; i++) {

    while (!greats.IsEmpty() && inputArr[i] > greats.PeekTop().Elem) {
        Pair top = greats.Pop();
        auxArr[top.Index] = i;
    }

    Pair p;
    p.Elem = inputArr[i];
    p.Index = i;

    greats.Push(p);
}

“Dizinin her elemanını yalnızca sabit sayıda düşündüğünüz için, bu O (n) zamandır.” Ah, kırılır. Her nasılsa O (n) olarak atarak birden fazla sürekli geçişi dışlamıştım. Çok aptal. Açıklamanız için minnettarım ve bir kez daha çözmeye çalışacağım.
Christopher Bitti
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.