ความต่อเนื่องที่เพิ่มขึ้นมากที่สุด


9

Sequence เป็นลำดับที่สามารถได้มาจากลำดับอื่นโดยการลบองค์ประกอบบางอย่างโดยไม่ต้องเปลี่ยนลำดับขององค์ประกอบที่เหลือ การต่อเนื่องที่เพิ่มขึ้นอย่างเข้มงวดเป็นส่วนประกอบที่ทุกองค์ประกอบมีขนาดใหญ่กว่าองค์ประกอบก่อนหน้า

ลำดับที่เพิ่มขึ้นที่หนักที่สุดของลำดับคือลำดับที่เพิ่มขึ้นอย่างเข้มงวดที่มีผลรวมองค์ประกอบที่ใหญ่ที่สุด

ใช้โปรแกรมหรือฟังก์ชั่นในภาษาที่คุณเลือกซึ่งจะหาผลรวมองค์ประกอบของลำดับที่เพิ่มขึ้นมากที่สุดของรายการจำนวนเต็มที่ไม่เป็นลบ

ตัวอย่าง:

                    [] ->  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])

โปรดทราบว่าคุณจะต้องให้ผลรวมองค์ประกอบของการเรียงลำดับที่เพิ่มขึ้นที่หนักที่สุดไม่ใช่ลำดับตัวเอง


โค้ดที่เร็วที่สุดแบบ asymptotically จะชนะโดยมีขนาดรหัสที่เล็กกว่าเป็นไบต์เป็นตัวแบ่ง


คุณวางแผนที่จะจัดการกับ asymptotics ที่เปรียบมิได้ได้อย่างไร อาจมีตัวแปรสำคัญสองตัว ได้แก่ ความยาวของลำดับและขนาดขององค์ประกอบที่ใหญ่ที่สุดในลำดับ
ปีเตอร์เทย์เลอร์

@ PeterTaylor ฉันเลือกความยาวของลำดับเป็นซีมโทติค วิธีการแก้ปัญหาของคุณจะต้องไม่ถือว่ามีจำนวนเต็มและโดยเฉพาะอย่างยิ่งไม่วนซ้ำหรือจัดสรรหน่วยความจำตามขนาดของตัวเลขที่เกี่ยวข้อง คุณได้รับการอภัยหากตัวเลือกภาษาของคุณมีจำนวนเต็ม แต่คุณต้องไม่ใช้ความจริงนี้ในการแก้ปัญหาของคุณ นั่นเป็นสิ่งที่ตอบสนองความกังวลของคุณหรือไม่?
orlp

เพียงบางส่วน ยังคงเป็นไปได้ในทางทฤษฎี (แม้ว่าอาจไม่น่าเป็นไปได้) ว่าความจริงที่ว่าการเปรียบเทียบจำนวนเต็มสองอันที่ไม่ จำกัด นั้นมีขนาดที่สัมพันธ์กับบันทึกของพวกเขาอาจเกี่ยวข้องกัน คุณอาจต้องการอนุญาตการดำเนินการขั้นพื้นฐาน (การเพิ่มการเปรียบเทียบอาจเป็นการทวีคูณ) ในจำนวนเต็มที่จะถือว่าเป็นเวลา O (1)
ปีเตอร์เทย์เลอร์

@PeterTaylor เป็นรูปแบบการคำนวณ transdichotomousเฉพาะเพียงพอหรือไม่
orlp

ดูเหมือนว่าสมเหตุสมผล
Peter Taylor

คำตอบ:


3

javascript (ES6) O(n log n)253 ตัวอักษร

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}

วิธีนี้ใช้ต้นเฟนวิค (ต้นเฟนวิคสูงสุด) เพื่อหาค่าสูงสุดของลำดับบางค่า

โดยพื้นฐานแล้วในอาเรย์พื้นฐานของประเภทข้อมูลแต่ละสถานที่จะถูกจับคู่กับองค์ประกอบจากรายการอินพุตตามลำดับเดียวกัน ต้นไม้เฟนวิคเริ่มต้นด้วย 0 ทุกที่

จากรายการที่เล็กที่สุดไปหามากที่สุดเราใช้องค์ประกอบจากรายการอินพุตและมองหาองค์ประกอบสูงสุดไปทางซ้าย พวกเขาเป็นองค์ประกอบที่อาจจะอยู่ก่อนหน้านี้ในการเรียงลำดับเพราะพวกเขาอยู่ทางซ้ายในลำดับการป้อนข้อมูลและมีขนาดเล็กเพราะพวกเขาเข้าไปในต้นไม้ก่อนหน้านี้

ดังนั้นจำนวนสูงสุดที่เราพบคือลำดับที่หนักที่สุดที่สามารถเข้าถึงองค์ประกอบนี้และเราเพิ่มน้ำหนักขององค์ประกอบนี้และตั้งไว้ในต้นไม้

จากนั้นเราก็คืนค่าสูงสุดของต้นไม้ทั้งหมดคือผลลัพธ์

ทดสอบกับ firefox


4

Python, O (n บันทึก n)

ฉันไม่ได้เล่นกอล์ฟเพราะฉันกำลังแข่งขันในด้านของโค้ดที่เร็วที่สุด วิธีการแก้ปัญหาของฉันคือheaviest_subseqฟังก์ชั่นและมีสายรัดทดสอบที่ด้านล่างด้วย

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))

การวิเคราะห์รันไทม์:

แต่ละองค์ประกอบมีตำแหน่งการแทรกค้นหาครั้งเดียวถูกแทรกครั้งเดียวและอาจถูกลบหนึ่งครั้งนอกเหนือจากการค้นหาค่าคงที่ต่อลูป เนื่องจากฉันใช้แพ็คเกจ bisect ในตัวและแพ็คเกจ blistการดำเนินการแต่ละอย่างนั้นจึงเป็นO(log n)เช่นนั้น O(n log n)ดังนั้นรันไทม์โดยรวมก็คือ

โปรแกรมทำงานโดยการรักษารายการเรียงลำดับที่ดีที่สุดที่เป็นไปได้เพิ่มขึ้นแสดงเป็น tuple ของค่าสิ้นสุดและผลรวมลำดับ การเรียงลำดับที่เพิ่มขึ้นอยู่ในรายการนั้นหากไม่พบส่วนประกอบอื่น ๆ ที่มีค่าสิ้นสุดน้อยกว่าและผลรวมมีค่าน้อยที่สุด เหล่านี้ถูกเก็บไว้ในลำดับที่เพิ่มขึ้นของค่าสิ้นสุดและจำเป็นต้องเพิ่มลำดับของผลรวมด้วยเช่นกัน คุณสมบัตินี้ได้รับการบำรุงรักษาโดยการตรวจสอบตัวตายตัวแทนของแต่ละลำดับใหม่ที่พบและลบออกถ้าผลรวมมีขนาดไม่ใหญ่พอและทำซ้ำจนกว่าจะถึงลำดับที่มีผลรวมที่มีขนาดใหญ่กว่าหรือถึงจุดสิ้นสุดของรายการ


น่าสนใจเป็นทางออกที่แตกต่างจากของฉันมาก
orlp

2

Python, O (n บันทึก n)

ฉันใช้การแปลงดัชนีและโครงสร้างข้อมูลที่ดี (ต้นไม้ดัชนีแบบไบนารี) เพื่อทำให้ปัญหาเล็กน้อย

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))

แผนภูมิดัชนีแบบไบนารีสามารถดำเนินการสองอย่างใน log (n): เพิ่มค่าที่ดัชนี i และรับค่าสูงสุดใน [0, i) เราเริ่มต้นทุกค่าในต้นไม้เป็น 0 เราจัดทำดัชนีต้นไม้โดยใช้ลำดับขององค์ประกอบไม่ใช่ดัชนี ซึ่งหมายความว่าหากเราจัดทำดัชนีต้นไม้ที่ดัชนี i องค์ประกอบทั้งหมด [0, i) เป็นองค์ประกอบที่เล็กกว่าที่มีอันดับที่ 1 ซึ่งหมายความว่าเราได้รับประโยชน์สูงสุดจาก [0, i), เพิ่มค่าปัจจุบันลงไปและทำการปรับปรุงที่ i ปัญหาเดียวก็คือว่าสิ่งนี้จะรวมถึงค่าที่น้อยกว่าค่าปัจจุบัน แต่มาในลำดับต่อมา แต่เนื่องจากเราเลื่อนไปตามลำดับจากซ้ายไปขวาและเราเริ่มต้นค่าทั้งหมดในทรีเป็น 0 ค่าเหล่านั้นจะมีค่า 0 และไม่ส่งผลกระทบต่อค่าสูงสุด


1

Python 2 - O(n^2)- 114 ไบต์

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 ไบต์

ควรได้รับการแก้ไขแล้ว:

#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>>();set<pair<I,I>> S;มีความยาวมากกว่าเพียงแค่ มีความยาวมากกว่า#define I int using I=int;ไม่มีความจำเป็นที่จะกำหนดให้เป็นnสิ่งที่คุณสามารถแทนที่ด้วยauto n=*prev(S.lower_bound({w,-1}));I y=n.second I y=prev(S.lower_bound({w,-1}))->second+w;
orlp

Oh, และการเริ่มต้นของการเป็นที่ซับซ้อนมากคุณก็สามารถนำแทรกและการใช้งานS std::set<std::pair<int,int>>S{{-1,0}};
orlp

@ orlp ขอบคุณ! มันแสดงให้เห็นว่าฉันไม่ได้ใช้ c ++;)
Tyilo

นี่เป็นรุ่นที่สั้นกว่ามาก (ยังคงต้องมีชุดและเวกเตอร์รวมอยู่ด้วย):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

โอ้และการถ่ายโอนข้อมูลการใช้งานstd::max W=y>W?y:W;
orlp


0

Python, O (2 n ), 91 ไบต์

นี่คือความสนุกมากกว่าที่จะแข่งขัน วิธีแก้ปัญหาแบบเรียกซ้ำ:

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])เพราะนั่นnot(l[0]<m)เป็นเพียงl[0]แน่นอน?
Peter Taylor

@PeterTaylor Derp
orlp

คำตอบนี้ดูเหมือนจะไม่เป็นคู่แข่งที่ร้ายแรง
pppery
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.