En ağır artan alt takım


9

Bir ardıllık, kalan öğelerin sırasını değiştirmeden bazı öğeleri silerek başka bir diziden türetilebilen bir dizidir. Kesinlikle artan bir alt çizgi, her öğenin öncekinden daha büyük olduğu bir alt dizidir.

Bir sekansın en ağır artan sekansı, en büyük element toplamına sahip olan kesinlikle artan sekanstır.

Belirli bir negatif olmayan tamsayılar listesinin en ağır artan alt sırasının öğe toplamını bulan kendi dilinizde bir program veya işlev uygulayın.

Örnekler:

                    [] ->  0 ([])
                   [3] ->  3 ([3])
             [3, 2, 1] ->  3 ([3])
          [3, 2, 5, 6] -> 14 ([3, 5, 6])
       [9, 3, 2, 1, 4] ->  9 ([9])
       [3, 4, 1, 4, 1] ->  7 ([3, 4])
       [9, 1, 2, 3, 4] -> 10 ([1, 2, 3, 4])
       [1, 2, 4, 3, 4] -> 10 ([1, 2, 3, 4])
[9, 1, 2, 3, 4, 5, 10] -> 25 ([1, 2, 3, 4, 5, 10])
       [3, 2, 1, 2, 3] ->  6 ([1, 2, 3])

Sadece en ağır artan alt sekansın eleman toplamını vermeniz gerektiğini unutmayın, alt sekansın kendisini değil.


Asemptotik olarak en hızlı kod kazanır, bir tiebreaker olarak bayt olarak daha küçük kod boyutu ile.


Eşsiz asimptotiklerle nasıl başa çıkmayı planlıyorsunuz? Potansiyel olarak iki önemli değişken vardır: dizinin uzunluğu ve dizideki en büyük elemanın boyutu.
Peter Taylor

@PeterTaylor Asimtotik olarak dizinin uzunluğunu seçiyorum. Çözümünüz, tamsayılar üzerinde herhangi bir sınırlama kabul etmemeli ve özellikle ilgili sayıların boyutuna göre bellek devretmemeli veya ayırmamalıdır. Dil seçiminizin tamsayılarla sınırlı olup olmadığı affedilir, ancak çözümünüzde bu gerçeği kullanmamalısınız. Endişelerinizi tatmin ediyor mu?
orlp

Kısmen. Teorik olarak (muhtemelen olası olmasa da), iki sınırsız tamsayı karşılaştırmasının günlükleriyle orantılı boyut alması önemli olabilir. Tamsayılarda temel işlemlerin (toplama, karşılaştırma, çarpma) O (1) zamanı olduğu varsayılabilir.
Peter Taylor

@PeterTaylor Transdichotomous hesaplama modeli yeterince spesifik mi?
orlp

Mantıklı görünüyor.
Peter Taylor

Yanıtlar:


3

javascript (ES6) O(n log n)253 karakter

function f(l){l=l.map((x,i)=>[x,i+1]).sort((a,b)=>a[0]-b[0]||1)
a=[0]
m=(x,y)=>x>a[y]?x:a[y]
for(t in l)a.push(0)
t|=0
for(j in l){for(i=(r=l[j])[1],x=0;i;i&=i-1)x=m(x,i)
x+=r[0]
for(i=r[1];i<t+2;i+=i&-i)a[i]=m(x,i)}for(i=t+1;i;i&=i-1)x=m(x,i)
return x}

Bu, belirli alt dizilerin maksimumlarını bulmak için fenwick ağaçları (maksimum fenwick ağacı) kullanır.

temel olarak, veri tipinin altında yatan dizide, her bir yer giriş listesindeki bir öğeyle aynı sırada eşleştirilir. fenwick ağacı her yerde 0 ile başlatılır.

en küçükten en büyüğe doğru, giriş listesinden bir öğe alırız ve soldaki öğelerin maksimumunu ararız. bunlar ardışıkta bundan önce olabilecek öğelerdir, çünkü giriş sırasında soldadırlar ve daha küçüktürler, çünkü daha önce ağaca girdiler.

bu yüzden bulduğumuz maksimum değer, bu öğeye ulaşabilecek en ağır dizidir ve bu yüzden buna bu öğenin ağırlığını ekleriz ve ağaca yerleştiririz.

o zaman, sonuç olarak tüm ağacın maksimumunu döndürürüz.

firefox'ta test edildi


4

Python, O (n log n)

Ben golf oynamadı, çünkü öncelikle şeylerin en hızlı kod tarafında rekabet ediyorum. Benim çözümüm heaviest_subseqişlevdir ve altta bir test koşum takımı da bulunur.

import bisect
import blist

def heaviest_subseq(in_list):
    best_subseq = blist.blist([(0, 0)])
    for new_elem in in_list:

        insert_loc = bisect.bisect_left(best_subseq, (new_elem, 0))

        best_pred_subseq_val = best_subseq[insert_loc - 1][1]

        new_subseq_val = new_elem + best_pred_subseq_val

        list_len = len(best_subseq)
        num_deleted = 0

        while (num_deleted + insert_loc < list_len
               and best_subseq[insert_loc][1] <= new_subseq_val):
            del best_subseq[insert_loc]
            num_deleted += 1

        best_subseq.insert(insert_loc, (new_elem, new_subseq_val))

    return max(val for key, val in best_subseq)

tests = [eval(line) for line in """[]
[3]
[3, 2, 1]
[3, 2, 5, 6]
[9, 3, 2, 1, 4]
[3, 4, 1, 4, 1]
[9, 1, 2, 3, 4]
[1, 2, 4, 3, 4]
[9, 1, 2, 3, 4, 5, 10]
[3, 2, 1, 2, 3]""".split('\n')]

for test in tests:
    print(test, heaviest_subseq(test))

Çalışma zamanı analizi:

Her öğenin ekleme konumu bir kez aranır, bir kez eklenir ve döngü başına sabit sayıda değer aramaya ek olarak muhtemelen bir kez silinir. Yerleşik bisect paketini ve blist paketini kullandığım için , bu işlemlerin her biri O(log n). Böylece, genel çalışma zamanı O(n log n).

Program, bitiş değeri ve sıra toplamının bir parçası olarak temsil edilen, mümkün olan en iyi artan sıralı dizilerin bir listesini tutarak çalışır. Bitiş değeri daha küçük olan ve toplamı en az büyük olan başka hiçbir altyazı yoksa, bu listede artan bir alt sıra bulunmaktadır. Bunlar artan bitiş sırası ve zorunlu olarak artan toplam sırası ile de korunur. Bu özellik, her yeni bulunan alt dizinin halefi kontrol edilerek ve toplamı yeterince büyük değilse silinerek ve daha büyük toplamı olan bir alt diziye ulaşılana veya listenin sonuna ulaşılana kadar tekrarlanarak korunur.


İlginç, benimkinden çok farklı bir çözüm .
orlp

2

Python, O (n log n)

Sorunu önemsizleştirmek için bir dizin dönüşümü ve şık bir veri yapısı (ikili dizinli ağaç) kullandım.

def setmax(a, i, v):
    while i < len(a):
        a[i] = max(a[i], v)
        i |= i + 1

def getmax(a, i):
    r = 0
    while i > 0:
        r = max(r, a[i-1])
        i &= i - 1
    return r

def his(l):
    maxbit = [0] * len(l)
    rank = [0] * len(l)
    for i, j in enumerate(sorted(range(len(l)), key=lambda i: l[i])):
        rank[j] = i

    for i, x in enumerate(l):
        r = rank[i]
        s = getmax(maxbit, r)
        setmax(maxbit, r, x + s)

    return getmax(maxbit, len(l))

İkili dizinlenmiş ağaç günlükte (n) iki işlem yapabilir: dizin i'de bir değeri artırın ve [0, i) 'de maksimum değeri alın. Ağaçtaki her değeri 0 olarak başlatırız. Ağacı, dizinlerini değil, öğelerin sırasını kullanarak dizinleriz. Bu, ağacı i dizininde endekslersek, tüm elemanlar [0, i), i derecesine sahip olandan daha küçük elemanlardır. Bu, maksimum değeri [0, i) elde ettiğimiz, geçerli değeri buna eklediğimiz ve i'de güncellediğimiz anlamına gelir. Tek sorun, bunun geçerli değerden daha az olan ancak daha sonra dizide yer alan değerleri içermesidir. Ancak sekansta soldan sağa hareket ettiğimiz ve ağaçtaki tüm değerleri 0'a başlattığımız için, bu değerler 0 değerine sahip olacak ve bu nedenle maksimumu etkilemeyecektir.


1

Python 2 - O(n^2)- 114 bayt

def h(l):
 w=0;e=[]
 for i in l:
    s=0
    for j,b in e:
     if i>j:s=max(s,b)
    e.append((i,s+i));w=max(w,s+i)
 return w

1

C ++ - O(n log n)- 261 bayt

Şimdi düzeltilmelidir:

#include <set>
#include <vector>
int h(std::vector<int>l){int W=0,y;std::set<std::pair<int,int>>S{{-1,0}};for(w:l){auto a=S.lower_bound({w,-1}),b=a;y=prev(a)->second+w;for(;b!=S.end()&&b->second<=y;b++){}a!=b?S.erase(a,b):a;W=y>W?y:W;S.insert({w,y});}return W;}

auto S=set<pair<I,I>>();sadece daha uzun set<pair<I,I>> S;. #define I intdaha uzun using I=int;. Atamak gerek yok nbir şey, sen yerine auto n=*prev(S.lower_bound({w,-1}));I y=n.secondsahip I y=prev(S.lower_bound({w,-1}))->second+w;.
orlp

Oh, ve başlatılması Sçok kıvrımlı, sadece eklentiden ve kullanımdan vazgeçebilirsiniz std::set<std::pair<int,int>>S{{-1,0}};.
orlp

@orlp teşekkürler! C ++;) kullanmadığımı gösteriyor
Tyilo

İşte çok daha kısa bir versiyon (hala set ve vektör dahil gerekir):using namespace std;using I=int;I h(vector<I>l){I W=0;set<pair<I,I>>S{{-1,0}};for(I w:l){I y=prev(S.lower_bound({w,-1}))->second+w;W=max(W,y);S.insert({w,y});}return W;}
orlp

Oh ve dök std::max, kullan W=y>W?y:W;.
orlp

0

Matlab, O ( n 2 n ), 90 bayt

function m=f(x)
m=0;for k=dec2bin(1:2^numel(x)-1)'==49
m=max(m,all(diff(x(k))>0)*x*k);end

Örnekler:

>> f([])
ans =
     0
>> f([3])
ans =
     3
>> f([3, 2, 5, 6])
ans =
    14

0

Python, O (2 n ), 91 bayt

Bu eğlenmek için rekabetçi olmaktan daha fazlasıdır. Gizli bir özyinelemeli çözüm:

h=lambda l,m=0:l and(h(l[1:],m)if l[0]<=m else max(h(l[1:],m),l[0]+h(l[1:],l[0])))or 0

1
max(m,l[0])tabii ki not(l[0]<m), sadece l[0]?
Peter Taylor

@PeterTaylor Derp.
orlp

Bu cevap ciddi bir rakip gibi görünmüyor.
pppery
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.