Scal dwie posortowane listy

14

Scal sortowanie

W tym wyzwaniu zaimplementujesz podprogram scalania sortowania scalającego. W szczególności musisz utworzyć funkcję, program, czasownik lub podobny, który pobierze dwie listy, każdą posortowaną w porządku rosnącym, i połączy je w jedną listę posortowaną w kolejności rosnącej. Wymagania:

- Twój algorytm musi zająć asymptotycznie liniowy czas w wielkości danych wejściowych. Przestańcie podawać rozwiązania O (n ^ 2).

  • Nie możesz używać żadnych wbudowanych funkcji zdolnych do sortowania listy, scalania listy lub czegokolwiek podobnego. Według uznania autora.
  • Kod powinien być w stanie obsłużyć powtarzające się elementy.
  • Nie martw się o puste listy.

Przykłady:

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]

To jest , więc może wygrać najkrótszy kod!

isaacg
źródło
Czy musimy obsługiwać powtarzające się elementy na liście, czy tylko między dwiema listami?
Keith Randall
Powiedzmy oba. Chodzi o to, że powinieneś być w stanie to wykorzystać do sortowania po scaleniu.
isaacg
Czy koszerne jest blokowanie tablic wejściowych?
skibrianski
3
Nie jestem pewien, jak interpretować algorytm musi zająć asymptotycznie liniowy czas . Algorytmy nie zajmują czasu, implementacje też. Czas wykonania mojej odpowiedzi w Golfscript to O (przerażający) w przypadku interpretera Ruby, ale Online Tester Golfscript zachowuje się znacznie lepiej i może w rzeczywistości być liniowy (choć nie jest to prawdziwy sposób mówienia bez kodu źródłowego). Chodzi mi o to: b=a;b=b.lengthmoże powielić całą tablicę a(i dać czas O (n ^ 2), jeśli zostanie wykonany dla każdego elementu) lub powielić tylko odniesienie do czasu tablicy (O (n)). Który się liczy?
Dennis,
1
Myślę, że w takich przypadkach staraj się to rozgryźć, ale jeśli naprawdę nie możesz powiedzieć, możesz założyć, że wszystko działa dobrze, jak druga wspomniana alternatywa. Możesz założyć, że tłumacz działa dobrze, jeśli twój język nie ma standardowego tłumacza.
isaacg

Odpowiedzi:

8

Rebmu ( 35 32 znaków)

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

Test

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

O

Rebmu jest dialektem Rebola, który pozwala na „musowanie” zwykłego kodu w sytuacjach wymagających zwięzłości. Unmushed, kod działa podobnie jak:

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)

Wierzę, że spełnia to wymóg O (n) , ponieważ blok till jest co najwyżej zapętlony tyle razy, ile długość wejściowa (a reversejedyna zmiana kolejności kontenerów bloków wejściowych, a nie samych bloków). Za pomocątake jest być może swobodą, ale wciąż stanowi niewielki hit wydajności.

Rebol ( 83 75 znaków)

Tylko trochę inaczej: w Rebol ścieżki są krótszym wyrażeniem niż firstlub second. ato blok wejściowy zawierający dwa bloki:

until[if a/2/1 < a/1/1[reverse a]append o:[]take a/1 tail? a/1]append o a/2
rgchris
źródło
5

Rozwiązania OP:

Haskell 49 44 40

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

Python 131 105 101 99 93

Dzięki dzięki @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
isaacg
źródło
1
Możesz pisać a%b=a++bpo dopasowaniu wzorca głównego, aby obsługiwać puste listy, które golą kilka znaków.
świst
czy rozwiązanie Haskell nie powiedzie się, jeśli na pierwszej liście zabraknie treści?
John Dvorak,
Jeśli spojrzysz na pierwszą funkcję, rekurencyjnie wywołuje funkcję ze skróconą listą jako drugim argumentem, a wydłużoną listę jako pierwszym argumentem, albo zamienia argumenty. Dlatego pierwszy argument nigdy się nie skraca. Ponieważ przez OP nie zaczyna się pusty, nigdy się nie opróżnia.
isaacg
4

Python (79)

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

Python (95, jeśli nie wolno nam zwrócić generatora)

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

Itertools to rozwiązanie wszystkich trudnych problemów.

Premia: dwie z nich pracują na dowolnej liczbie list i martwią się o puste listy (jak w tym przypadku, chętnie wezmą 2 puste listy i zwrócą pustą listę, lub wezmą 1 pustą i 1 niepustą listę, i zwrócą niepuste. Kolejna dodana funkcja dwóch niewydanych: będą one również działać bez argumentów i po prostu zwrócą pustą listę).

Nie golfowany:

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
.ıʇǝɥʇuʎs
źródło
W rozwiązaniach bez generatora używaj r+=[...]zamiast r.append(...)(zapisuje 4 znaki za każdym razem)
hlt
Nie mam tu na myśli żadnych obrażeń, ale jeśli twoja odpowiedź zawiera kod w języku, który jest po prostu innym językiem z modyfikacjami stworzonymi specjalnie do gry w golfa, zamierzam go głosować. Szkoda, prawdziwe odpowiedzi na python są dobre.
undergroundmonorail
Jeśli podzielisz je na różne posty, głosuję za pythonem.
undergroundmonorail
4
@undergroundmonorail Czy głosujesz negatywnie na wszystkie odpowiedzi w GolfScript?
Evpok
1
@Evpok Teraz, kiedy o tym wspominasz, równie dobrze możesz rzucić to na meta i zobaczyć, co mają do powiedzenia.
8ıʇǝɥʇuʎs
3

C - 75

Działa to na NULLtablicach zakończonych int *, choć działałoby równie dobrze dla wskaźników do innych typów, zastępując odpowiednią funkcję porównania **b < **a(np strcmp(*b, *a) < 0.).

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

Nie golfowany:

void merge(int **a, int **b, int **c)
{
    while(*a || *b)
        *c++ = !*a || *b && **b < **a
            ? *b++
            : *a++;
}
laindir
źródło
3

Golfscript, 29 27 30 29 26 bajtów

~{[email protected]=@<{}{\}if(@@.}do;~]p

lub

~{[email protected]=@>{\}*(@@.}do;~]p

Jak to działa

Komenda

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

będą przetwarzane w następujący sposób:

~            # 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.

Dane wyjściowe to:

[1 2 3 4]
Dennis
źródło
Czy powielanie tablic w stosie powoduje, że jest to O (n ^ 2)?
swish
@swish: Nie jestem informatykiem, ale powiedziałbym, że to zależy od implementacji. Jeśli interpreter faktycznie powiela całe tablice, to chyba tak.
Dennis
Poprzednia wersja to O (n ^ 2) dla bardzo podobnych tablic (np. [1 1 1 ... 2]I [1 1 1 ... 3]), ponieważ porównywanie tablic (a nie ich pierwszych elementów) byłoby w tym przypadku bardzo powolne.
Dennis,
Jedynymi operacjami tablicowymi, które mają miejsce w nowej wersji, są duplikacja, zamiana i obrót stosu. Ponieważ zduplikowane tablice są używane tylko do wyodrębnienia pojedynczych elementów i przetestowania tablic pod kątem nieopróżnienia (obie destrukcyjne operacje w Golfscript), powyższy kod można uruchomić w czasie O (n) (przez powielenie, zamianę i obrócenie odniesień do tablice). Rzeczywista wydajność zależy od tłumacza.
Dennis,
2

J - 42 33

Zmodyfikowana wersja stąd + komentarz @algorithmshark

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

kdołącza nagłówek prawej tablicy do scalonych ogonów obu tablic. k~jest taki sam, ale z odwróconymi tablicami. (>&{.)porównuje głowy. Kod zgłosi błąd, jeśli jedna z tablic jest pusta, w takim przypadku zwracamy tylko ich konkatenację ,.

śmigać
źródło
Zakładam, że skoro /:~ a,bjest to odpowiedź zabroniona (wraz z [:/:~,), że strzelasz do najkrótszej odpowiedzi, która nie zawiera /:, prawda?
Dane
Zwrócę uwagę, że pytanie brzmi: „Nie martw się pustymi listami”.
Dane
@Dane Test pustki wymagany do zatrzymania rekurencji.
swish
m=:k~`k@.(>&{.)`,@.(0=*&#)oszczędza 2 znaki
algorytmshark
W rzeczywistości możesz sprowadzić całość do 33 znaków: k=:(m}.),~0{]i m=:k~`k@.(>&{.) ::,. Używamy, 0{aby zgłosić błąd, gdy lista jest pusta, a następnie złapać ten błąd i wyjść z ,.
algorytmshark
2

JavaScript (ES6), 69 79 bajtów

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

Jak to działa

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'.
                               //
)
Dennis
źródło
Porównanie tablic z <operatorem nie jest prawidłowe, ponieważ dokonuje porównania ciągów:f([123, 456, 789], [1, 2, 3, 4, 5]) => [1, 123, 2, 3, 4, 456, 5, 789]
nderscore
@nderscore: Racja. I tak by to nie zadziałało, ponieważ porównywanie całych tablic może nie być O (n). To samo wydaje się dotyczyć testu nieopróżnienia, który musi przekonwertować całą tablicę na ciąg.
Dennis,
Tak, nie jestem pewien, co to jest big-o dla konwersji typu tablica-> ciąg znaków.
nderscore
1
Łączenie tablicy z, []a następnie konwertowanie jej na ciąg wymaga O (n) czasu. Wykonanie tego raz dla wszystkich n elementów tablicy zajmuje czas O (n ^ 2).
Dennis,
Ma sens. Rozumiem.
nderscore
2

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

Napisałem to, zanim zobaczyłem komentarze OP dotyczące środowisk wykonawczych innych odpowiedzi, więc jest to kolejne rozwiązanie, które O (n) w algorytmie, ale nie implementacja.

xnor
źródło
Jakie algorytmy mają wyciągi z przodu tablic jako O (1)? Jakie algorytmy mają porównania list przyjmujące O (1)? Możesz także
zagrać w
@isaacg Strzelaj, zapomniałem o powtórzeniach, które mogłyby spowodować porównanie listy O (n). Wyjąłem więc tę optymalizację dla kolejnych 6 znaków. Możesz wyodrębnić i dołączyć z przodu w O (1) na połączonej liście. Nie rozumiem, jak możesz ... i ... lub ... dobrze się bawić zwracając wartość.
xnor
OK, teraz widzę, jak to zrobić ... i ... lub ..., ale nie oszczędza znaków z powodu potrzebnych parenów. return[a.pop(0)]+(a and m(a,b)or b)
xnor
@isaacg: Aby wyodrębnić przód tablicy w O (1), wystarczy zwiększyć wskaźnik tablicy tak, aby wskazywał na drugi element i zwolnić pamięć zajętą ​​przez pierwszy element.
Wrzlprmft
@Wrzlprmft Nie udało mi się uruchomić sztuczki tablicowej, ponieważ oba elementy tablicy są oceniane niezależnie od wartości logicznej, co powoduje błąd, gdy a jest pustą listą. Czy istnieje krótki sposób na stworzenie „leniwej tablicy”?
xnor
2

Haskell, 35 bajtów

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

Haskell, 30 bajtów (niekonkurencyjny)

Ta niekonkurencyjna wersja gwarantuje liniowe działanie tylko wtedy, gdy a i bmają elementy rozłączne; w przeciwnym razie nadal działa poprawnie, ale może zająć kwadratowy czas.

a#b|a<b=b#a|c:d<-b=c:a#d
a#_=a
Anders Kaseorg
źródło
2

PHP 91 98 91 bajtów

edycja nr 1: Pusta $b wymaga dodatkowego warunku w nawiasach klamrowych (+7).
edycja nr 2: drobne gra w golfa
edycja nr 3: dodano drugą wersję

całkiem prosto. Najładniejszą częścią jest trójskładnik wewnątrzarray_shift
(który zawiedzie, jeśli spróbujesz go bez kręconych)

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

lub

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

bez golfa

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;
}

test

$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>';
Tytus
źródło
Nie mogłem zrozumieć, dlaczego $a&(!$b|$a[0]<$b[0])?$a:$bzamiast tego nie jest to proste${$a&(!$b|$a[0]<$b[0])?a:b}
Jörg Hülsermann,
1
@ JörgHülsermann array_shiftParametr jest używany przez odniesienie. To musi być zmienna; wyrażenie nie zadziała.
Tytus
1

Idź, 124 znaki

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...)}
Keith Randall
źródło
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))}

Takie samo podejście jak PO.

Matt
źródło
1

perl, 87 znaków / perl 5.14, 78 + 1 = 79 znaków

Ta implementacja blokuje odwołania do tablic wejściowych. Poza tym jest to dość proste: podczas gdy obie tablice mają coś, przesuń niższą z dwóch. Następnie zwróć scalony bit połączony z pozostałymi bitami (pozostanie tylko jeden z @ $ x lub @ $ y). Prosto perl5, 87 znaków:

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

Używając perla 5.14.0 i jego nowej zmiany tablicy: 78 znaków + 1 kara kary = 79 znaków:

sub M{($x,$y,@o)=@_;push@o,shift($$x[0]>$$y[0]?$y:$x)while@$x&&@$y;@o,@$x,@$y}
skibrianski
źródło
*zamiast &&zapisuje bajt. A nawet więcej, jeślisub M{map{shift(!@$x+@$y*($$y[0]<$$x[0])?$y:$x)}map@$_,($x,$y)=@_}
użytkownik2846289
@VadimR, wow. dobra robota. Śmiało, opublikuj to, jeśli chcesz - nigdy bym nie pomyślał o zrobieniu podwójnej mapy zamiast naciskać na tablicę.
skibrianski
1

Java: 144

To jest całkiem proste. Funkcja, która pobiera dwie tablice i zwraca jedną, wersję scaloną, golfa i bez opakowania kompilacji:

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 (z opcją kompilacji i uruchamiania):

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;
    }
}

Przykładowe wykonania:

$ 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

Wszelkie wskazówki dotyczące skrócenia byłyby mile widziane.

ProgrammerDan
źródło
1

Scala, 97 bajtów

Rozwiązanie rekurencyjne z O (n). Aby skrócić kod, czasami wykonuje się operację przez zmianę 2 wymiennych parametrów, tj. Wywołań f (a, b) 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)

Nie golfowany:

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)
lambruscoAcido
źródło
Wyjątek, jeśli a nie jest puste, ale b jest puste
Dan Osipov
1

APL (32)

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

Wyjaśnienie:

{⍺⍵∊⍨⊂⍬                               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
marinus
źródło
1

LISP, 117 bajtów

Algorytm kończy się n + 1iteracjami, gdzie njest długością najkrótszej listy na wejściu.

(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))))))))
PieCot
źródło
0

PYG (50)

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

PYG (ponownie 64, jeśli nie są dozwolone żadne generatory.):

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

Adaptacja mojej odpowiedzi w języku Python .

.ıʇǝɥʇuʎs
źródło
0

Python - 69 bajtów

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

Gdyby kolejność wejścia i wyjścia była malejąca, można to skrócić do 61 bajtów :

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

I dalej do 45 bajtów, jeśli dozwolone są generatory:

def m(A,B):
    while A+B:yield[A,B][A<B].pop(0)
Wrzlprmft
źródło
To zdecydowanie nie jest O (n). .pop (0) i + = są operacjami O (n), które wykonujesz O (n) razy.
isaacg
Do tej pory nawet nie wiedziałem, że listy nie są zaimplementowane jako listy w Pythonie i nawet wtedy pop(0)mogą być zaimplementowane w O (1) i +=przynajmniej mogą być zaimplementowane lepiej niż O (n) (patrz link). Nawiasem mówiąc, twoje rozwiązanie używa +=(tj. appendI extend) tak często jak moje. W każdym razie, wszystko to jest pytanie implementacyjne (o ile mi wiadomo), więc w (fikcyjnej) implementacji Pythona, gdzie listy są implementowane jako listy, moją funkcją jest O (n). Wreszcie twoje pytanie wymagało, aby algorytm był O (n), a mój jest.
Wrzlprmft
W rzeczywistości dodawanie i rozszerzanie są zaimplementowane w Pythonie inaczej niż + =. + = tworzy nową listę, a .append i .extend modyfikują istniejącą.
isaacg
0

Perl 6: 53 znaków

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

Przejdź od dowolnej z wartości alub bma mniejszą wartość, aż aXOR b( a^b) będzie prawdziwe. Następnie zwróć wszystko, co pozostało, spłaszczając ( []) tablice do listy ( a[],b[]).

Zakładając, że przesunięcie od początku tablicy wynosi O (n), najgorszym przypadkiem są dwa porównania i jedno przesunięcie na element, więc algorytm to O (n).

Mouq
źródło
0

JavaScript (ES5) 90 86 90 bajtów

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

edytować: (90 -> 86) Przeniesiono trójskładnik do warunku pętli for. Pomysł skradziony Dennisowi.

edit: (86 -> 90) Usunięto rzutowanie Array na String, ponieważ łamie wymaganie O (n) .

nderscore
źródło
0

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

Wejście:

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

Wynik:

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

Nie golfowany:

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
)

Prawdopodobnie może być lepiej.

kukac67
źródło
m[a:{x___,y_},b:{___,z_}]:=If[y<z,b~m~a,{x}~m~b~Join~{y}];{}~m~b_=b;
alephalpha
0

R, 80

Takie samo rozwiązanie jak w Scali i innych językach. Nie jestem pewien, czy x [-1] to 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
lambruscoAcido
źródło
0

Mathematica, 104 bajty

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

Funkcja anonimowe przechowuje długość dwóch listy zmiennych wejściowych mi n, wówczas każdy iteracji Dopętli Sows elementem jednej listy zwiększając licznik tej listy ( iw pierwszym, kw drugim) o jeden. Jeśli jeden z liczników przekroczy długość listy, Ifinstrukcja zawsze będzie Sowelementem z drugiej listy. Po n+moperacji zadbano o wszystkie elementy. Reapa raczej część [[2,1]]jego danych wyjściowych to lista elementów w kolejności, w jakiej były Sown.

Nie jestem pewien, czy dane wewnętrzne (uzyskują dostęp do części listy, O(1)czy nie), ale czasy na mojej maszynie wyglądały dość liniowo w odniesieniu do długości listy danych wejściowych.

LLAMAMYP
źródło