Sau đó tăng nặng nhất


9

Một chuỗi là một chuỗi có thể được bắt nguồn từ một chuỗi khác bằng cách xóa một số phần tử mà không thay đổi thứ tự của các phần tử còn lại. Phần tiếp theo tăng nghiêm ngặt là phần tiếp theo trong đó mọi phần tử đều lớn hơn phần trước.

Phần tiếp theo tăng mạnh nhất của chuỗi là phần tăng dần nghiêm ngặt có tổng phần tử lớn nhất.

Thực hiện một chương trình hoặc hàm theo ngôn ngữ bạn chọn để tìm tổng phần tử của phần tăng dần nặng nhất của một danh sách các số nguyên không âm.

Ví dụ:

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

Lưu ý rằng bạn chỉ phải đưa ra tổng phần tử của phần tiếp theo tăng nặng nhất, chứ không phải chính phần tiếp theo.


Mã nhanh nhất không có triệu chứng sẽ thắng, với kích thước mã nhỏ hơn tính bằng byte như một bộ bẻ khóa.


Làm thế nào để bạn có kế hoạch để đối phó với tiệm cận không thể so sánh? Có khả năng có hai biến quan trọng: độ dài của chuỗi và kích thước của phần tử lớn nhất trong chuỗi.
Peter Taylor

@PeterTaylor Tôi chọn độ dài của chuỗi là tiệm cận. Giải pháp của bạn không được thừa nhận bất kỳ ràng buộc nào trên các số nguyên và đặc biệt không lặp hoặc phân bổ bộ nhớ dựa trên kích thước của các số liên quan. Bạn được tha thứ nếu lựa chọn ngôn ngữ của bạn có giới hạn số nguyên, nhưng bạn không được sử dụng thực tế này trong giải pháp của mình. Điều đó có thỏa mãn mối quan tâm của bạn không?
orlp

Một phần. Về mặt lý thuyết vẫn có thể (mặc dù có lẽ là không thể) rằng việc so sánh hai số nguyên không liên kết có kích thước tỷ lệ thuận với nhật ký của chúng có thể có liên quan. Bạn có thể muốn cho phép các hoạt động cơ bản (cộng, so sánh, có thể nhân) trên các số nguyên được giả sử là thời gian O (1).
Peter Taylor

@PeterTaylor Mô hình tính toán transdichotomous có đủ cụ thể không?
orlp

Có vẻ hợp lý.
Peter Taylor

Câu trả lời:


3

javascript (ES6) O(n log n)253 ký tự

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}

điều này sử dụng cây fenwick (một cây fenwick tối đa) để tìm cực đại của các chuỗi con nhất định.

về cơ bản, trong mảng cơ bản của kiểu dữ liệu, mỗi vị trí được khớp với một phần tử từ danh sách đầu vào, theo cùng một thứ tự. cây fenwick được khởi tạo với 0 ở khắp mọi nơi.

từ nhỏ nhất đến lớn nhất, chúng tôi lấy một phần tử từ danh sách đầu vào và tìm tối đa các phần tử ở bên trái. chúng là các phần tử có thể nằm trước phần này trong phần tiếp theo, vì chúng nằm bên trái trong chuỗi đầu vào và nhỏ hơn, vì chúng đã nhập vào cây trước đó.

Vì vậy, mức tối đa chúng tôi tìm thấy là chuỗi nặng nhất có thể đến phần tử này và vì vậy chúng tôi thêm vào trọng số của phần tử này và đặt nó trong cây.

sau đó, chúng ta chỉ cần trả về mức tối đa của toàn bộ cây là kết quả.

đã thử nghiệm trên firefox


4

Python, O (n log n)

Tôi không chơi gôn này, vì tôi thi đấu chủ yếu ở khía cạnh mã nhanh nhất. Giải pháp của tôi là heaviest_subseqchức năng, và một khai thác thử nghiệm cũng được bao gồm ở phía dưới.

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

Phân tích thời gian chạy:

Mỗi phần tử có vị trí chèn của nó được tra cứu một lần, được chèn một lần và có thể bị xóa một lần, ngoài số lần tra cứu giá trị không đổi trên mỗi vòng lặp. Vì tôi đang sử dụng gói bisect tích hợp và gói vỉ , nên mỗi thao tác đó đều được O(log n). Vì vậy, thời gian chạy tổng thể là O(n log n).

Chương trình hoạt động bằng cách duy trì một danh sách được sắp xếp các chuỗi tăng tốt nhất có thể, được biểu diễn dưới dạng một bộ giá trị kết thúc và tổng chuỗi. Một chuỗi con tăng dần nằm trong danh sách đó nếu không có chuỗi con nào khác được tìm thấy cho đến nay có giá trị kết thúc nhỏ hơn và tổng ít nhất là lớn. Chúng được duy trì theo thứ tự tăng dần của giá trị kết thúc, và nhất thiết cũng theo thứ tự tăng dần. Thuộc tính này được duy trì bằng cách kiểm tra sự kế thừa của mỗi chuỗi con mới tìm thấy và xóa nó nếu tổng của nó không đủ lớn và lặp lại cho đến khi đạt được một chuỗi với số tiền lớn hơn hoặc kết thúc danh sách.


Thật thú vị, một giải pháp rất khác với tôi .
orlp

2

Python, O (n log n)

Tôi đã sử dụng một biến đổi chỉ mục và một cấu trúc dữ liệu tiện lợi (cây được lập chỉ mục nhị phân) để tầm thường hóa vấ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))

Cây được lập chỉ mục nhị phân có thể thực hiện hai thao tác trong log (n): tăng giá trị tại chỉ mục i và nhận giá trị tối đa trong [0, i). Chúng tôi khởi tạo mọi giá trị trong cây thành 0. Chúng tôi lập chỉ mục cho cây bằng cách sử dụng thứ hạng của các phần tử, chứ không phải chỉ mục của chúng. Điều này có nghĩa là nếu chúng ta lập chỉ mục cây ở chỉ mục i, tất cả các phần tử [0, i) là các phần tử nhỏ hơn phần tử có thứ hạng i. Điều này có nghĩa là chúng tôi nhận được tối đa từ [0, i), thêm giá trị hiện tại vào nó và cập nhật nó tại i. Vấn đề duy nhất là điều này sẽ bao gồm các giá trị nhỏ hơn giá trị hiện tại, nhưng đến sau trong chuỗi. Nhưng vì chúng ta di chuyển qua chuỗi từ trái sang phải và chúng ta đã khởi tạo tất cả các giá trị trong cây thành 0, nên các giá trị này sẽ có giá trị 0 và do đó không ảnh hưởng đến mức tối đa.


1

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

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 byte

Nên sửa ngay:

#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>>();dài hơn đơn giản set<pair<I,I>> S;. #define I intdài hơn using I=int;. Không cần phải gán ncho bất cứ điều gì, bạn có thể thay thế auto n=*prev(S.lower_bound({w,-1}));I y=n.secondbằng I y=prev(S.lower_bound({w,-1}))->second+w;.
orlp

Ồ, và việc khởi tạo Srất phức tạp, bạn có thể bỏ qua phần chèn và sử dụng std::set<std::pair<int,int>>S{{-1,0}};.
orlp

@orlp cảm ơn! Nó cho thấy rằng tôi không sử dụng c ++;)
Tyilo

Đây là phiên bản ngắn hơn nhiều (vẫn cần tập hợp và vectơ bao gồm):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 và đổ std::max, sử dụng W=y>W?y:W;.
orlp

0

Matlab, O ( n 2 n ), 90 byte

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

Ví dụ:

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

0

Python, O (2 n ), 91 byte

Đây là nhiều hơn cho niềm vui hơn là cạnh tranh. Một giải pháp đệ quy phức tạp:

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])cho rằng đó not(l[0]<m)chỉ là l[0], chắc chắn?
Peter Taylor

@PeterTaylor Derp.
orlp

Câu trả lời này dường như không phải là một ứng cử viên nghiêm trọng.
pppery
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.