Hợp nhất hai danh sách được sắp xếp


14

Hợp nhất sắp xếp

Trong thử thách này, bạn sẽ thực hiện chương trình con hợp nhất của sắp xếp hợp nhất. Cụ thể, bạn phải tạo một chức năng hoặc chương trình hoặc động từ hoặc tương tự có hai danh sách, mỗi danh sách được sắp xếp theo thứ tự tăng dần và kết hợp chúng thành một danh sách được sắp xếp theo thứ tự tăng dần. Yêu cầu:

- Thuật toán của bạn phải mất một lượng thời gian tuyến tính bất đối xứng trong kích thước của đầu vào. Hãy ngừng đưa ra giải pháp O (n ^ 2).

  • Bạn không được sử dụng bất kỳ chức năng tích hợp nào có khả năng sắp xếp danh sách hoặc hợp nhất danh sách hoặc bất cứ thứ gì tương tự. Theo ý của tác giả.
  • Mã sẽ có thể xử lý các yếu tố lặp đi lặp lại.
  • Đừng lo lắng về danh sách trống.

Ví dụ:

merge([1],[0,2,3,4])
[0,1,2,3,4]

merge([1,5,10,17,19],[2,5,9,11,13,20])
[1, 2, 5, 5, 9, 10, 11, 13, 17, 19, 20]

Đây là , vì vậy có thể đoạn mã ngắn nhất sẽ thắng!


Chúng ta có phải xử lý các yếu tố lặp đi lặp lại trong một danh sách, hoặc chỉ giữa hai danh sách?
Keith Randall

Hãy nói cả hai. Ý tưởng là bạn sẽ có thể sử dụng điều này để thực hiện sắp xếp hợp nhất.
isaacg

Có phải kosher để ghi đè các mảng đầu vào?
skibrianski

3
Tôi không chắc làm thế nào để giải thích thuật toán phải mất một lượng thời gian tuyến tính không có triệu chứng . Các thuật toán không mất thời gian, thực hiện. Thời gian thực hiện câu trả lời Golfscript của tôi là O (đáng sợ) với trình thông dịch Ruby, nhưng Trình kiểm tra Golf trực tuyến hoạt động tốt hơn nhiều và thực tế có thể là tuyến tính (mặc dù không có cách nói thực sự nào nếu không có mã nguồn). Quan điểm của tôi là: b=a;b=b.lengthcó thể nhân đôi toàn bộ mảng a(và kết quả là thời gian O (n ^ 2) nếu được thực thi cho mọi phần tử) hoặc sao chép chỉ tham chiếu đến thời gian của mảng (O (n)). Cái nào được tính?
Dennis

1
Tôi đoán trong những trường hợp như thế này, chỉ cần cố gắng hết sức để tìm ra nó, nhưng nếu bạn thành thật không thể nói, bạn có thể cho rằng mọi thứ hoạt động tốt, như phương án thứ hai bạn đã đề cập. Bạn có thể cho rằng trình thông dịch hoạt động tốt nếu ngôn ngữ của bạn không có trình thông dịch chuẩn.
isaacg

Câu trả lời:


8

Rebmu ( 35 32 ký tự)

u[iG^aNXa[rvA]apGtkFaM?fA]apGscA

Kiểm tra

>> rebmu/args [u[iG^aNXa[rvA]apGtkFaM?fA]apGscA] [[1 5 10 17 19] [2 5 9 11 13 20]] 
== [1 2 5 5 9 10 11 13 17 19 20]

>> rebmu/args [u[iG^aNXa[rvA]apGtkFaM?fA]apGscA] [[2 5 9 11 13 20] [1 5 10 17 19]] 
== [1 2 5 5 9 10 11 13 17 19 20]

Trong khoảng

Rebmu là một phương ngữ của Rebol cho phép 'kết hợp' mã thông thường cho các tình huống cần sự ngắn gọn. Không bị làm mờ, mã hoạt động hơi giống như:

u [                     ; until
    i g^ a nx a [       ; if greater? args next args
       rv a             ; reverse args
    ]                   ; (we want the block containing the next value first)

    ap g tk f a         ; append output take first args
    m? f a              ; empty? first args
]                       ; (first block is now empty)

ap g sc a               ; append output second args
                        ; (add the remainder of the second)

Tôi tin rằng điều này thỏa mãn yêu cầu O (n) vì khối cho đến khi nhiều nhất được lặp nhiều lần bằng chiều dài của đầu vào (và reversechỉ chuyển đổi thứ tự của bộ chứa của các khối đầu vào, chứ không phải chính các khối). Sử dụng takecó lẽ là một tự do, nhưng vẫn là một hiệu quả nhỏ.

Rebol ( 83 75 ký tự)

Chỉ khác một chút: trong Rebol, đường dẫn là biểu thức ngắn hơn firsthoặc second. alà khối đầu vào chứa hai khối:

until[if a/2/1 < a/1/1[reverse a]append o:[]take a/1 tail? a/1]append o a/2

5

Giải pháp của OP:

Haskell 49 44 40

k@(p:r)%l@(q:s)|p>=q=q:k%s|0<1=l%k
a%_=a

Con trăn 131 105 101 99 93

Cảm ơn @Evpok:

f=lambda u,v:v and(v[-1]<u[-1]and f(v,u)or[b.append(a)for a,b in[(v.pop(),f(u,v))]]and b)or u

1
Bạn có thể viết a%b=a++bsau khi khớp mẫu chính để xử lý các danh sách trống, sẽ loại bỏ vài ký tự.
swish

giải pháp Haskell không thành công nếu danh sách đầu tiên hết nội dung trước?
John Dvorak

Nếu bạn nhìn vào hàm đầu tiên, nó sẽ gọi hàm đó với danh sách rút gọn là đối số thứ hai và danh sách dài là đối số thứ nhất hoặc nếu không thì hoán đổi các đối số. Do đó, đối số đầu tiên không bao giờ ngắn hơn. Vì OP không bắt đầu trống nên nó sẽ không bao giờ trống.
isaacg

4

Con trăn (79)

from itertools import*
def m(*a):
 while any(a):yield min(compress(a,a)).pop(0)

Python (95, nếu chúng tôi không được phép trả lại trình tạo)

from itertools import*
def m(*a):
 r=[]
 while any(a):r+=[min(compress(a,a)).pop(0)]
 return r

Itertools là giải pháp cho tất cả các vấn đề thế giới.

Phần thưởng: hai trong số này hoạt động với số lượng danh sách tùy ý và KHÔNG lo lắng về danh sách trống (như trong, họ sẽ vui vẻ nhận 2 danh sách trống và trả về một danh sách trống hoặc lấy 1 danh sách trống và 1 danh sách trống, và họ sẽ trả lại cái không trống. Một tính năng bổ sung khác của 2 cái không mang lại: chúng cũng sẽ chạy mà không có đối số và chỉ trả về một danh sách trống.)

Ung dung:

from itertools import *  # Import all items from itertools
def m(*a):               # Define the function m, that takes any number of arguments, 
                         #  and stores those arguments in list a
    r=[]                 # Create an empty list r                         
    while any(a):        # While any element in a returns True as value:
        b=compress(a,a)  # Remove any element from a that isn't True (empty lists)
                         #  The example in the official documentation is this one:
                         #  compress('ABCDEF', [1,0,1,0,1,1]) --> A C E F
        c=min(b)         # Sort the lists by first value, and take the first one of these.
        d=c.pop(0)       # Take the first element from c
        r.append(d)      # Append this first element to r
    return r             # Gives back r

Trong các giải pháp của bạn không có máy phát điện, hãy sử dụng r+=[...]thay vì r.append(...)(tiết kiệm 4 ký tự mỗi lần)
hlt

Tôi không có ý xúc phạm điều này, nhưng nếu câu trả lời của bạn chứa mã bằng ngôn ngữ chỉ là ngôn ngữ khác với các sửa đổi được thực hiện riêng cho việc chơi gôn, tôi sẽ từ chối nó. Thật là xấu hổ, câu trả lời trăn thực sự là tốt.
undergroundmonorail

Nếu bạn chia chúng thành các bài viết khác nhau, tôi sẽ nâng cấp con trăn.
undergroundmonorail

4
@undergroundmonorail Bạn có đánh giá thấp tất cả các câu trả lời của GolfScript không?
Evpok

1
@Evpok Bây giờ bạn đề cập đến nó, cũng có thể ném nó lên meta, và xem những gì họ nói ở đó.
ɐɔıʇǝɥʇuʎs

3

C - 75

Điều này hoạt động trên NULLcác mảng kết thúc int *, mặc dù nó sẽ hoạt động tốt như nhau đối với các con trỏ đến các loại khác bằng cách thay thế hàm so sánh thích hợp cho **b < **a(ví dụ strcmp(*b, *a) < 0:).

void m(int**a,int**b,int**c){while(*a||*b)*c++=!*a||*b&&**b<**a?*b++:*a++;}

Ung dung:

void merge(int **a, int **b, int **c)
{
    while(*a || *b)
        *c++ = !*a || *b && **b < **a
            ? *b++
            : *a++;
}

3

Golf, 29 27 30 29 26 byte

~{.0=@.0=@<{}{\}if(@@.}do;~]p

hoặc là

~{.0=@.0=@>{\}*(@@.}do;~]p

Làm thế nào nó hoạt động

Lệnh

golfscript merge.gs <<< '[2 3] [1 4]'

sẽ được xử lý như sau:

~            # Interpret the input string.
             #
             # STACK: [2 3] [1 4]
{            #
    .@=0.@=0 # Duplicate the two topmost arrays of the stack and extract their first 
             # elements. This reverses the original order of the first copy.
             #
             # STACK: [1 4] [2 3] 2 1
             #
    >        # Check if the respective first elements of the arrays are ordered.
             #
             # STACK: [1 4] [2 3] 1
             #
    {\}*     # If they are not, swap the arrays. This brings the array with the smallest
             # element to the top of the stack.
             #
             # STACK: [2 3] [1 4]
             #
    (@@      # Shift the first element of the array on top of the stack and rotate it
             # behind the arrays.
             #
             # STACK: 1 [2 3] [4]
             #
    .        # Duplicate the topmost array.
             #
             # STACK: 1 [2 3] [4] [4]
             #
}do          # Repeat this process if the array is non-empty.
             #
             # STACK: 1 [2 3] [4] -> 1 2 [4] [3] -> 1 2 3 [4] []
             #
;~           # Delete the empty array from the stack and dump the non-empty array.
             #
             # STACK: 1 2 3 4
             #
]p           # Combine all elements on the stack into a single array, the to a string and
             # print.

Đầu ra là:

[1 2 3 4]

Sự trùng lặp của các mảng trong ngăn xếp có làm cho nó O (n ^ 2) không?
swish

@swish: Tôi không phải là nhà khoa học máy tính, nhưng tôi muốn nói nó phụ thuộc vào việc thực hiện. Nếu trình thông dịch thực sự sao chép toàn bộ mảng, tôi đoán là có.
Dennis

Phiên bản trước là O (n ^ 2) cho các mảng rất giống nhau (ví dụ: [1 1 1 ... 2][1 1 1 ... 3]), vì so sánh các mảng (chứ không phải là các phần tử đầu tiên của chúng) sẽ rất chậm trong trường hợp này.
Dennis

Các hoạt động mảng duy nhất diễn ra trong phiên bản mới là sao chép, hoán đổi và xoay trên ngăn xếp. Do các mảng trùng lặp chỉ được sử dụng để trích xuất các phần tử đơn lẻ và kiểm tra các mảng không trống (cả hai hoạt động phá hủy trong Golfscript), mã trên có thể được chạy trong thời gian O (n) (bằng cách sao chép, hoán đổi và xoay các tham chiếu đến mảng). Hiệu suất thực tế phụ thuộc vào người phiên dịch.
Dennis

2

J - 42 33

Phiên bản sửa đổi từ đây + nhận xét của @alerskymshark

k=:(m}.),~0{]
m=:k~`k@.(>&{.) ::,

kchuẩn bị phần đầu của mảng bên phải cho các đuôi được hợp nhất của cả hai mảng. k~là như nhau, nhưng với các mảng lật. (>&{.)đang so sánh những người đứng đầu. Mã sẽ đưa ra một lỗi nếu một trong các mảng trống, trong trường hợp đó chúng ta chỉ trả lại kết nối của chúng ,.


Tôi đoán rằng vì đó /:~ a,blà câu trả lời bị cấm (cùng với [:/:~,), rằng bạn đang chụp cho câu trả lời ngắn nhất không bao gồm /:, phải không?
Dane

Tôi sẽ chỉ ra rằng câu hỏi nêu rõ, "Đừng lo lắng về danh sách trống."
Dane

@Dane Thử nghiệm cho sự trống rỗng cần thiết cho đệ quy dừng lại.
swish

m=:k~`k@.(>&{.)`,@.(0=*&#)tiết kiệm 2 char.
thuật toán

Trong thực tế, bạn có thể giảm toàn bộ xuống còn 33 char: k=:(m}.),~0{]m=:k~`k@.(>&{.) ::,. Chúng tôi sử dụng 0{để đưa ra một lỗi khi danh sách trống, sau đó bắt lỗi đó và thoát với ,.
thuật toán

2

JavaScript (ES6), 69 79 byte

f=(a,b,c=[])=>(x=a[0]<b[0]?a:b).length?f(a,b,c.concat(x.shift())):c.concat(a,b)

Làm thế nào nó hoạt động

f = (a, b, c = []) =>          // `f' is a function that takes arguments `a', `b' and `c' -
                               // `c' defaults to `[]' - which returns the following
                               // expression:
                               //
 (x = a[0] < b[0] ? a : b)     // Store the array among `a' and `b' with the smaller first 
                               // element in `x'.
                               //
 .length ?                     // If it's non-empty,
                               //
  f(a, b, c.concat(x.shift())) // append the first element of array `x' to array `c' and run
                               // `f' again;
                               //
  : c.concat(a,b)              // otherwise, append the arrays `a' and `b' to `c'.
                               //
)

So sánh các mảng với <toán tử không hợp lệ vì nó so sánh chuỗi:f([123, 456, 789], [1, 2, 3, 4, 5]) => [1, 123, 2, 3, 4, 456, 5, 789]
nderscore

@nderscore: Phải. Dù sao thì nó cũng không hoạt động, vì so sánh toàn bộ mảng có thể không phải là O (n). Điều tương tự cũng có vẻ đúng đối với thử nghiệm không trống, phải chuyển đổi toàn bộ mảng thành một chuỗi.
Dennis

Vâng, tôi không chắc chắn big-o cho mảng-> chuyển đổi loại chuỗi là gì.
nderscore

1
Ghép một mảng với []và sau đó chuyển đổi nó thành một chuỗi đòi hỏi thời gian O (n). Làm như vậy một lần cho tất cả n phần tử của mảng mất thời gian O (n ^ 2).
Dennis

Có ý nghĩa. Hiểu rồi.
nderscore

2

Con trăn (63) (69) (71)

def m(a,b):
 if a[0]>b[0]:a,b=b,a
 return[a.pop(0)]+(m(a,b)if a else b)

Tôi đã viết điều này trước khi thấy những bình luận của OP về thời gian chạy của các câu trả lời khác, vì vậy đây là một giải pháp khác là thuật toán O (n) nhưng không triển khai.


Những thuật toán nào đã trích xuất từ ​​phía trước của mảng là O (1)? Những thuật toán nào có danh sách so sánh lấy O (1)? Ngoài ra, bạn có thể đánh gôn thêm bằng cách thay đổi ... nếu ... khác ... thành ... và ... hoặc ...
isaacg

@isaacg Shoot, tôi đã quên về việc lặp lại có thể làm cho danh sách so sánh O (n). Vì vậy, tôi đã đưa ra tối ưu hóa đó cho thêm 6 ký tự. Bạn có thể trích xuất từ ​​và nối vào mặt trước trong O (1) trong danh sách được liên kết. Tôi không thấy cách bạn có thể làm ... và ... hoặc ... chơi đẹp khi trả lại giá trị.
xnor

OK, tôi thấy bây giờ làm thế nào để làm ... và ... hoặc ..., nhưng nó không tiết kiệm được ký tự do số liệu cần thiết. return[a.pop(0)]+(a and m(a,b)or b)
xnor

@isaacg: Để trích xuất mặt trước của một mảng trong O (1), chỉ cần tăng con trỏ mảng sao cho nó trỏ đến phần tử thứ hai và giải phóng bộ nhớ được sử dụng bởi phần tử đầu tiên.
Wrzlprmft

@Wrzlprmft Tôi không thể làm cho thủ thuật mảng hoạt động được vì cả hai phần tử của mảng được đánh giá bất kể giá trị boolean, sẽ đưa ra lỗi khi a là danh sách trống. Có một cách ngắn để tạo ra một "mảng lười biếng"?
xnor

2

Haskell, 35 byte

a#b@(c:d)|a<[c]=b#a|0<1=c:a#d
a#_=a

Haskell, 30 byte (không cạnh tranh)

Phiên bản không cạnh tranh này chỉ đảm bảo thời gian chạy tuyến tính nếu abcó các yếu tố rời rạc; mặt khác, nó vẫn chạy chính xác nhưng có thể sử dụng thời gian bậc hai.

a#b|a<b=b#a|c:d<-b=c:a#d
a#_=a

2

PHP 91 98 91 byte

chỉnh sửa # 1: Làm trống $byêu cầu một điều kiện bổ sung trong dấu ngoặc nhọn (+7).
chỉnh sửa # 2: đánh gôn nhỏ
chỉnh sửa # 3: thêm phiên bản thứ hai

khá thẳng về phía trước. Phần đẹp nhất là ternary bên trong array_shift
(sẽ thất bại nếu bạn thử nó mà không có xoăn)

function m($a,$b){for($c=[];$a|$b;)$c[]=array_shift(${$a&(!$b|$a[0]<$b[0])?a:b});return$c;}

hoặc là

function m($a,$b){for($c=[];$a|$b;)$c[]=array_shift(${$a?!$b|$a[0]<$b[0]?a:b:b});return$c;}

vô dụng

function m($a,$b)
{
    $c=[];
    while($a||$b)
    {
        $c[] = array_shift(${
            $a&&(!$b||$a[0]<$b[0])
                ?a
                :b
        });
#       echo '<br>', outA($a), ' / ', outA($b) , ' -> ', outA($c);
    }
    return $c;
}

kiểm tra

$cases = array (
    [1],[0,2,3,4], [0,1,2,3,4],
    [1,5,10,17,19],[2,5,9,11,13,20], [1, 2, 5, 5, 9, 10, 11, 13, 17, 19, 20],
    [1,2,3],[], [1,2,3],
    [],[4,5,6], [4,5,6],
);
function outA($a) { return '['. implode(',',$a). ']'; }
echo '<table border=1><tr><th>A</th><th>B</th><th>expected</th><th>actual result</th></tr>';
while ($cases)
{
    $a = array_shift($cases);
    $b = array_shift($cases);
#   echo '<hr>', outA($a), ' / ', outA($b) , ' -> ', outA($c);
    $expect = array_shift($cases);
    $result=m($a,$b);
    echo '<tr><td>',outA($a),'</td><td>',outA($b),'</td><td>', outA($expect), '</td><td>', outA($result),'</td></tr>';
}
echo '</table>';

Tôi không thể hiểu tại sao bạn làm cho nó không đơn giản $a&(!$b|$a[0]<$b[0])?$a:$bthay vì${$a&(!$b|$a[0]<$b[0])?a:b}
Jörg Hülsermann

1
@ JörgHülsermann array_shiftTham số được sử dụng bởi tham chiếu. Nó phải là một biến số; một biểu hiện đã thắng công việct.
Tít

1

Đi, 124 ký tự

func m(a,b[]int)(r[]int){for len(a)>0{if len(b)==0||a[0]>b[0]{a,b=b,a}else{r=append(r,a[0]);a=a[1:]}};return append(r,b...)}

1

JavaScript - 133

function m(a,b){c=[];for(i=j=0;i<a.length&j<b.length;)c.push(a[i]<b[j]?a[i++]:b[j++]);return c.concat(a.slice(i)).concat(b.slice(j))}

Cách tiếp cận tương tự như của OP.


1

perl, 87 ký tự / perl 5.14, 78 + 1 = 79 ký tự

Việc thực hiện này ghi đè các tham chiếu mảng đầu vào. Ngoài ra, nó khá đơn giản: trong khi cả hai mảng đều có thứ gì đó, hãy dịch chuyển xuống phía dưới của hai mảng. Sau đó trả về bit đã hợp nhất được nối với bất kỳ bit nào còn lại (chỉ còn lại một trong số @ $ x hoặc @ $ y). Straight-up perl5, 87 ký tự:

sub M{($x,$y,@o)=@_;push@o,$$x[0]>$$y[0]?shift@$y:shift@$x while@$x&&@$y;@o,@$x,@$y}

Sử dụng perl 5.14.0 và dịch chuyển mảng mới của nó: 78 ký tự + 1 hình phạt char = 79 ký tự:

sub M{($x,$y,@o)=@_;push@o,shift($$x[0]>$$y[0]?$y:$x)while@$x&&@$y;@o,@$x,@$y}

*thay vì &&sẽ tiết kiệm một byte. Và thậm chí nhiều hơn nếusub M{map{shift(!@$x+@$y*($$y[0]<$$x[0])?$y:$x)}map@$_,($x,$y)=@_}
user2846289

@VadimR, wow. công việc tốt đẹp. Hãy tiếp tục và đăng rằng nếu bạn thích - tôi sẽ không bao giờ nghĩ sẽ thực hiện thủ thuật bản đồ đôi thay vì đẩy vào một mảng.
skibrianski

1

Java: 144

Việc này thật thẳng thắn. Một hàm có hai mảng và trả về một, phiên bản được hợp nhất, được đánh gôn và không có trình bao bọc biên dịch:

int[]m(int[]a,int[]b){int A=a.length,B=b.length,i,j;int[]c=new int[A+B];for(i=j=0;i+j<A+B;c[i+j]=j==B||i<A&&a[i]<b[j]?a[i++]:b[j++]);return c;}

Ungolfed (với trình bao bọc có thể biên dịch và có thể chạy được):

class M{
    public static void main(String[]args){
        int[]a=new int[args[0].split(",").length];
        int i=0;
        for(String arg:args[0].split(","))
            a[i++]=Integer.valueOf(arg);
        int[]b=new int[args[1].split(",").length];
        int j=0;
        for(String arg:args[1].split(","))
            b[j++]=Integer.valueOf(arg);
        int[]c=(new M()).m(a,b);
        for(int d:c)
            System.out.printf(" %d",d);
        System.out.println();
    }
    int[]m(int[]a,int[]b){
        int A=a.length,B=b.length,i,j;
        int[]c=new int[A+B];
        for(i=j=0;i+j<A+B;c[i+j]=j==B||i<A&&a[i]<b[j]?a[i++]:b[j++]);
        return c;
    }
}

Ví dụ thực hiện:

$ javac M.java
$ java M 10,11,12 0,1,2,20,30
 0 1 2 10 11 12 20 30
$ java M 10,11,12,25,26 0,1,2,20,30
 0 1 2 10 11 12 20 25 26 30

Bất kỳ lời khuyên để rút ngắn sẽ được đánh giá cao.


1

Scala, 97 byte

Giải pháp đệ quy với O (n). Để rút ngắn mã, đôi khi một thao tác được thực hiện bằng cách chuyển đổi 2 tham số có thể hoán đổi cho nhau, tức là f (a, b) gọi f (b, a).

type L=List[Int];def f(a:L,b:L):L=if(a==Nil)b else if(a(0)<=b(0))a(0)::f(a.drop(1),b) else f(b,a)

Ung dung:

type L=List[Int]

def f(a:L, b:L) : L =
  if (a == Nil)
    b 
  else 
    if (a(0) <= b(0))
      a(0) :: f(a.drop(1), b) 
    else
      f(b,a)

Ngoại lệ nếu a không trống, nhưng b trống
Dan Osipov

1

APL (32)

{⍺⍵∊⍨⊂⍬:⍺,⍵⋄g[⍋g←⊃¨⍺⍵],⊃∇/1↓¨⍺⍵}

Giải trình:

{⍺⍵∊⍨⊂⍬                               if one or both of the arrays are empty
        :⍺,⍵                           then return the concatenation of the arrays
             ⋄g[⍋g←⊃¨⍺⍵]              otherwise return the sorted first elements of both arrays
                          ,⊃∇/        followed by the result of running the function with
                               1↓¨⍺⍵}  both arrays minus their first element

1

LISP, 117 byte

Thuật toán kết thúc bằng các n + 1lần lặp, trong đó nđộ dài của danh sách ngắn nhất trong đầu vào.

(defun o(a b)(let((c(car a))(d(car b)))(if(null a)b(if(null b)a(if(< c d)(cons c(o(cdr a)b))(cons d(o a(cdr b))))))))

0

PYG (50)

def m(*a):
 while An(a):yield Mn(ItCo(a,a)).pop(0)

PYG (64, một lần nữa, nếu không cho phép máy phát điện.):

def m(*a):
 r=[]
 while An(a):r+=[(Mn(ItCo(a,a)).pop(0)]
 return r

Một bản phóng tác của câu trả lời Python của tôi .


0

Python - 69 byte

def m(A,B):
    C=[]
    while A and B:C+=[[A,B][A>B].pop(0)]
    return C+A+B

Nếu thứ tự đầu vào và đầu ra giảm dần, điều này có thể được rút ngắn xuống còn 61 byte :

def m(A,B):
    C=[]
    while A+B:C+=[[A,B][A<B].pop(0)]
    return C

Và tiếp tục xuống tới 45 byte nếu máy phát điện được cho phép:

def m(A,B):
    while A+B:yield[A,B][A<B].pop(0)

Đây chắc chắn không phải là O (n). .pop (0) và + = là cả hai thao tác O (n) bạn thực hiện O (n) lần.
isaacg

Tôi thậm chí còn không biết rằng danh sách không được triển khai dưới dạng danh sách trong Python và thậm chí sau đó pop(0)có thể được triển khai trong O (1) và +=ít nhất có thể được triển khai tốt hơn O (n) (xem liên kết). Nhân tiện, giải pháp của bạn sử dụng +=(nghĩa là appendextend) thường xuyên như của tôi. Dù sao, tất cả đó là một câu hỏi triển khai (theo như tôi biết), vì vậy trong một triển khai Python (hư cấu), trong đó các danh sách được thực hiện dưới dạng danh sách, chức năng của tôi là O (n). Cuối cùng, câu hỏi của bạn yêu cầu thuật toán là O (n) và của tôi là.
Wrzlprmft

Trên thực tế, chắp thêm và mở rộng được triển khai khác nhau trong python so với + = is. + = tạo một danh sách mới, trong khi .append và .extend sửa đổi một danh sách hiện có.
isaacg

0

Perl 6: 53 ký tự

sub M(\a,\b){{shift a[0]>b[0]??b!!a}...{a^b},a[],b[]}

Thay đổi từ bất kỳ ahoặc bcó giá trị nhỏ hơn, cho đến khi aXOR b( a^b) là đúng. Sau đó trả lại bất cứ thứ gì còn lại, làm phẳng ( []) các mảng vào danh sách ( a[],b[]).

Giả sử dịch chuyển từ đầu một mảng là O (n), trường hợp xấu nhất là hai so sánh và một thay đổi cho mỗi phần tử, vì vậy thuật toán là O (n).


0

JavaScript (ES5) 90 86 90 byte

function f(a,b){for(o=[];(x=a[0]<b[0]?a:b).length;)o.push(x.shift());return o.concat(a,b)}

chỉnh sửa: (90 -> 86) Đã chuyển ternary vào điều kiện vòng lặp for. Ý tưởng bị đánh cắp từ Dennis.

chỉnh sửa: (86 -> 90) Loại bỏ mảng thành chuỗi, vì nó phá vỡ yêu cầu O (n) .


0

Toán học, 137 135

m[a_,b_]:=(l=a;Do[Do[If[b[[f]]<=l[[s]],(l=Insert[l,b[[f]],s];Break[]),If[s==Length@l,l=l~Append~b[[f]]]],{s,Length@l}],{f,Length@b}];l)

Đầu vào:

m[{2,2,4,6,7,11},{1,2,3,3,3,3,7}]

Đầu ra:

{1, 2, 2, 2, 3, 3, 3, 3, 4, 6, 7, 7, 11}

Ung dung:

mergeList[a_, b_] := (
    list = a;
    Do[
        Do[(
            If[
                b[[f]] <= list[[s]],
                (list = Insert[list, b[[f]], s]; Break[]),
                If[
                    s == Length@list,
                    list = list~Append~b[[f]]
                ]
        ]),
        {s, Length@list}
    ],
    {f, Length@b}
    ];
    list
)

Có lẽ có thể làm tốt hơn.


m[a:{x___,y_},b:{___,z_}]:=If[y<z,b~m~a,{x}~m~b~Join~{y}];{}~m~b_=b;
alephalpha

0

R, 80

Giải pháp tương tự như trong Scala và các ngôn ngữ khác. Tôi không chắc chắn về x [-1] là O (1).

f=function(a,b)if(length(a)){if(a[1]<=b[1])c(a[1],f(a[-1],b))else f(b,a)}else b

0

Toán học, 104 byte

Reap[{m,n}=Length/@{##};i=k=1;Do[If[k>n||TrueQ[#[[i]]<#2[[k]]],Sow@#[[i++]],Sow@#2[[k++]]],n+m]][[2,1]]&

Hàm ẩn danh, lưu trữ độ dài của hai danh sách đầu vào trong các biến mnsau đó mỗi lần lặp của Dovòng lặp Sowlà một phần tử của một danh sách tăng bộ đếm cho danh sách đó ( icho lần đầu tiên, kcho lần thứ hai). Nếu một trong các bộ đếm vượt quá độ dài của danh sách, Ifcâu lệnh sẽ luôn Sowlà phần tử từ danh sách khác. Saun+m hoạt động, tất cả các yếu tố đã được chăm sóc.Reaphay đúng hơn là một phần [[2,1]]của đầu ra của nó là một danh sách các phần tử theo thứ tự chúng đã được Sown.

Tôi không chắc chắn về phần bên trong (có truy cập vào một phần của danh sách O(1)hoạt động hay không), nhưng thời gian trông khá tuyến tính trên máy của tôi đối với độ dài danh sách đầu vào.

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.