Zwei sortierte Listen zusammenführen


14

Zusammenführen, sortieren

In dieser Challenge implementieren Sie die Merge-Subroutine von merge sort. Insbesondere müssen Sie eine Funktion oder ein Programm, ein Verb oder Ähnliches erstellen, das zwei Listen verwendet, die in aufsteigender Reihenfolge sortiert sind, und diese in einer Liste zusammenfasst, die in aufsteigender Reihenfolge sortiert ist. Bedarf:

- Ihr Algorithmus muss eine asymptotisch lineare Zeit in der Größe der Eingabe benötigen. Bitte geben Sie keine O (n ^ 2) -Lösungen mehr an.

  • Sie dürfen keine integrierten Funktionen verwenden, mit denen eine Liste sortiert oder zusammengeführt werden kann. Ermessen des Autors.
  • Der Code sollte in der Lage sein, wiederholte Elemente zu verarbeiten.
  • Mach dir keine Sorgen über leere Listen.

Beispiele:

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]

Das ist , also kann der kürzeste Code gewinnen!


Müssen wir wiederholte Elemente innerhalb einer Liste oder nur zwischen den beiden Listen behandeln?
Keith Randall

Sagen wir beides. Die Idee ist, dass Sie in der Lage sein sollten, Mergesort durchzuführen.
Isaacg

Ist es koscher, die Eingabearrays zu überlasten?
Skibrianski

3
Ich bin nicht sicher, wie der Algorithmus zu interpretieren ist, muss eine asymptotisch lineare Zeitspanne in Anspruch nehmen . Algorithmen brauchen keine Zeit, Implementierungen schon. Die Ausführungszeit meiner Golfscript-Antwort ist mit dem Ruby-Interpreter O (beängstigend), aber der Online-Golfscript-Tester verhält sich viel besser und könnte tatsächlich linear sein (ohne den Quellcode jedoch keine echte Art zu erzählen). Mein Punkt ist: b=a;b=b.lengthkönnte das gesamte Array duplizieren a(und zu O (n ^ 2) -Zeit führen, wenn es für jedes Element ausgeführt wird) oder nur den Verweis auf das Array duplizieren (O (n) -Zeit). Welches zählt?
Dennis

1
Ich denke, in solchen Fällen geben Sie einfach Ihr Bestes, um es herauszufinden, aber wenn Sie ehrlich gesagt nicht sagen können, können Sie davon ausgehen, dass die Dinge gut funktionieren, wie bei der zweiten Alternative, die Sie erwähnt haben. Sie können davon ausgehen, dass der Dolmetscher gut funktioniert, wenn Ihre Sprache keinen Standarddolmetscher hat.
Isaacg

Antworten:


8

Rebmu ( 35 32 Zeichen)

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

Prüfung

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

Über

Rebmu ist ein Dialekt von Rebol, der es erlaubt, in Situationen, die Kürze erfordern, regulären Code zu „mushen“. Unmushed funktioniert der Code wie folgt:

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)

Ich glaube, dass dies die O (n) -Anforderung erfüllt, da der till-Block höchstens so oft wie die Länge der Eingabe durchgeschleift wird (und reversenur die Reihenfolge des Containers der Eingabeblöcke ändert, nicht die Blöcke selbst). Verwenden takeist vielleicht eine Freiheit, aber immer noch ein kleiner Effizienzschaden.

Rebol ( 83 75 Zeichen)

Nur ein kleines bisschen anders: In Rebol sind Pfade ein kürzerer Ausdruck als firstoder second. aist der Eingabeblock, der die beiden Blöcke enthält:

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

5

OP's Lösungen:

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

Mit Dank an @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
Sie können a%b=a++bnach dem Hauptmustervergleich schreiben , um leere Listen zu bearbeiten, die einige Zeichen abschneiden.
Swish

Schlägt die Haskell-Lösung nicht fehl, wenn der ersten Liste zuerst der Inhalt ausgeht?
John Dvorak

Wenn Sie sich die erste Funktion ansehen, ruft sie die Funktion rekursiv mit der verkürzten Liste als zweitem Argument und der verlängerten Liste als erstem Argument auf oder tauscht die Argumente aus. Daher wird das erste Argument nie kürzer. Da es vom OP nicht leer gestartet wird, wird es niemals leer.
Isaacg

4

Python (79)

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

Python (95, wenn wir keinen Generator zurückgeben dürfen)

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

Itertools ist die Lösung für alle weltweiten Probleme.

Bonus: Die beiden arbeiten an einer beliebigen Anzahl von Listen und sorgen sich um leere Listen (wie in, nehmen sie gerne 2 leere Listen und geben eine leere Liste zurück oder nehmen 1 leere und 1 nicht leere Liste, und sie werden die nicht leere zurückgeben. Ein weiteres zusätzliches Merkmal der 2 nicht ergebenden: Sie werden auch ohne Argumente ausgeführt und geben nur eine leere Liste zurück.)

Ungolfed:

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

Verwenden Sie in Ihren Lösungen ohne Generator r+=[...]anstelle von r.append(...)(spart jedes Mal 4 Zeichen)
hlt

Ich meine damit keine Beleidigung, aber wenn Ihre Antwort Code in einer Sprache enthält, die nur eine andere Sprache ist, deren Änderungen speziell für das Golfen vorgenommen wurden, werde ich sie ablehnen. Es ist eine Schande, die richtigen Python-Antworten sind gut.
Undergroundmonorail

Wenn du sie in verschiedene Posts aufteilst, stimme ich der Python-Version zu.
Undergroundmonorail

4
@undergroundmonorail Stimmen Sie alle GolfScript-Antworten ab?
Evpok

1
@Evpok Nun, da Sie es erwähnen, können Sie es auch auf Meta werfen und sehen, was sie dort zu sagen haben.
ɐɔıɐɔuʇǝɥʇs

3

C - 75

Dies funktioniert auf NULLterminierten Arrays von int *, obwohl es für Zeiger auf andere Typen genauso gut funktionieren würde, wenn die entsprechende Vergleichsfunktion für **b < **a(z strcmp(*b, *a) < 0. B. ) eingesetzt würde.

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

Ungolfed:

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

3

Golfscript, 29 27 30 29 26 Bytes

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

oder

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

Wie es funktioniert

Der Befehl

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

wird wie folgt verarbeitet:

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

Die Ausgabe ist:

[1 2 3 4]

Macht das Duplizieren von Arrays im Stapel es zu O (n ^ 2)?
Swish

@swish: Ich bin kein Informatiker, aber ich würde sagen, es hängt von der Implementierung ab. Wenn der Interpreter tatsächlich die gesamten Arrays dupliziert, ist dies vermutlich der Fall.
Dennis

Die vorherige Version war O (n ^ 2) für sehr ähnliche Arrays (z. B. [1 1 1 ... 2]und [1 1 1 ... 3]), da das Vergleichen der Arrays (und nicht ihrer ersten Elemente) in diesem Fall sehr langsam wäre.
Dennis

Die einzigen Array-Operationen, die in der neuen Version ausgeführt werden, sind Duplizieren, Austauschen und Drehen auf dem Stapel. Da die duplizierten Arrays nur verwendet werden, um einzelne Elemente zu extrahieren und die Arrays auf Nicht-Leere zu testen (beides destruktive Operationen in Golfscript), kann der obige Code in O (n) Zeit ausgeführt werden (durch Duplizieren, Vertauschen und Drehen der Verweise auf Arrays). Die tatsächliche Leistung hängt vom Dolmetscher ab.
Dennis

2

J - 42 33

Geänderte Version von hier + der Kommentar von @algorithmshark

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

kStellt den Kopf des rechten Arrays vor die zusammengeführten Endpunkte beider Arrays. k~ist das gleiche, aber mit umgedrehten Arrays. (>&{.)vergleicht die Köpfe. Der Code wird einen Fehler auslösen, wenn eines der Arrays leer ist. In diesem Fall geben wir nur ihre Verkettung zurück ,.


Ich gehe davon aus , dass Sie , da /:~ a,bdie verbotene Antwort (zusammen mit [:/:~,) ist, für die kürzeste Antwort schießen, die es nicht gibt /:, oder?
Däne

Ich werde darauf hinweisen, dass in der Frage steht: "Mach dir keine Sorgen über leere Listen."
Däne

@Dane Der Test auf Leere, der erforderlich ist, damit die Rekursion beendet wird.
Swish

m=:k~`k@.(>&{.)`,@.(0=*&#)spart 2 Zeichen
Algorithmushai

Tatsächlich können Sie das Ganze auf 33 Zeichen reduzieren: k=:(m}.),~0{]und m=:k~`k@.(>&{.) ::,. Wir verwenden, 0{um einen Fehler zu werfen, wenn die Liste leer ist, und diesen Fehler dann abzufangen und mit zu beenden ,.
Algorithmushai

2

JavaScript (ES6), 69 bis 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)

Wie es funktioniert

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'.
                               //
)

Der Vergleich der Arrays mit dem <Operator ist nicht gültig, da hier ein Stringvergleich durchgeführt wird:f([123, 456, 789], [1, 2, 3, 4, 5]) => [1, 123, 2, 3, 4, 456, 5, 789]
nderscore

@nderscore: Richtig. Es hätte sowieso nicht funktioniert, da der Vergleich der gesamten Arrays möglicherweise nicht O (n) ist. Gleiches scheint für den Nicht-Leertest zu gelten, bei dem das gesamte Array in einen String umgewandelt werden muss.
Dennis

Ja, ich bin mir nicht sicher, wie hoch der Wert für Array-> String-Typ-Konvertierung ist.
Nderscore

1
Das Verketten eines Arrays mit []und das anschließende Umwandeln in einen String erfordert O (n) Zeit. Dies einmal für alle n Elemente des Arrays zu tun, benötigt O (n ^ 2) Zeit.
Dennis

Macht Sinn. Ich habs.
Unterstrich

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)

Ich habe dies geschrieben, bevor ich die Kommentare von OP zu den Laufzeiten anderer Antworten gesehen habe. Dies ist also eine andere Lösung, die O (n) im Algorithmus, aber keine Implementierung ist.


Welche Algorithmen haben Auszüge aus der Vorderseite von Arrays als O (1)? Welche Algorithmen haben Listenvergleiche mit O (1)? Außerdem können Sie Golf spielen, indem Sie ... wenn ... sonst ... zu ... und ... oder ...
wechseln

@isaacg Shoot, ich hatte die Wiederholungen vergessen, die möglicherweise den Listenvergleich O (n) ergeben. Also habe ich diese Optimierung für 6 weitere Zeichen herausgenommen. Sie können in einer verknüpften Liste aus O (1) extrahieren und an O (1) anhängen. Ich verstehe nicht, wie Sie ... und ... oder ... mit der Rückgabe des Wertes spielen können.
XNOR

OK, ich verstehe jetzt, wie es geht ... und ... oder ..., aber es spart keine Zeichen aufgrund der benötigten Parens. return[a.pop(0)]+(a and m(a,b)or b)
XNOR

@isaacg: Um die Vorderseite eines Arrays in O (1) zu extrahieren, erhöhen Sie einfach den Array-Zeiger so, dass er auf das zweite Element zeigt, und geben Sie den vom ersten Element belegten Speicher frei.
Wrzlprmft

@Wrzlprmft Ich konnte den Array-Trick nicht zum Laufen bringen, da beide Elemente des Arrays unabhängig vom booleschen Wert ausgewertet werden, was einen Fehler auslöst, wenn a die leere Liste ist. Gibt es einen kurzen Weg, um ein "Lazy Array" zu machen?
Donnerstag,

2

Haskell, 35 Bytes

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

Haskell, 30 Bytes (nicht konkurrierend)

Diese nicht konkurrierende Version garantiert nur dann eine lineare Laufzeit, wenn aund bmit disjunkten Elementen. Andernfalls wird es weiterhin ordnungsgemäß ausgeführt, es wird jedoch möglicherweise eine quadratische Zeit verwendet.

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

2

PHP 91 98 91 Bytes

edit # 1: Leer $berfordert eine zusätzliche Bedingung in den geschweiften Klammern (+7).
edit # 2: Minor Golfings
edit # 3: Zweite Version hinzugefügt

ziemlich einfach. Der schönste Teil ist der Dreiklang in der array_shift
(was fehlschlägt, wenn Sie es ohne die Locken versuchen)

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

oder

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

ungolfed

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

Prüfung

$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>';

Ich konnte nicht verstehen , warum Sie es nicht einfach machen , $a&(!$b|$a[0]<$b[0])?$a:$banstatt${$a&(!$b|$a[0]<$b[0])?a:b}
Jörg Hülsermann

1
@ JörgHülsermann Der array_shiftParameter wird als Referenz verwendet. Es muss eine Variable sein; Ein Ausdruck wird nicht funktionieren.
Titus

1

Los, 124 Zeichen

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

Gleiche Vorgehensweise wie bei OPs.


1

Perl, 87 Zeichen / Perl 5,14, 78 + 1 = 79 Zeichen

Diese Implementierung überlastet die Referenzen der Eingabearrays. Davon abgesehen ist es ziemlich einfach: Während beide Arrays etwas haben, verschieben Sie die untere der beiden. Geben Sie dann das zusammengeführte Bit zurück, das mit den verbleibenden Bits verbunden ist (es bleibt nur eines von @ $ x oder @ $ y übrig). Straight-Up Perl5, 87 Zeichen:

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

Unter Verwendung von Perl 5.14.0 und seiner neuen Arrayref-Verschiebung: 78 Zeichen + 1 Zeichen Strafe = 79 Zeichen:

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

*Statt &&wird ein Byte gespeichert. Und noch mehr, wennsub M{map{shift(!@$x+@$y*($$y[0]<$$x[0])?$y:$x)}map@$_,($x,$y)=@_}
user2846289

@ VadimR, wow. gute Arbeit. Wenn Sie möchten, können Sie dies hier veröffentlichen. Ich hätte nie gedacht, dass Sie den Double-Map-Trick ausführen, anstatt auf ein Array zu drücken.
Skibrianski

1

Java: 144

Das ist ziemlich einfach. Eine Funktion, die zwei Arrays verwendet und eines zurückgibt, die zusammengeführte Version, golfen und ohne Compilation-Wrapper:

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 (mit kompilierbarem und lauffähigem Wrapper):

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

Beispielausführungen:

$ 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

Alle Tipps zu verkürzen wäre dankbar.


1

Scala, 97 Bytes

Rekursive Lösung mit O (n). Um den Code zu verkürzen, wird manchmal eine Operation durchgeführt, indem die 2 austauschbaren Parameter umgeschaltet werden, dh f (a, b) ruft f (b, a) auf.

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)

Ungolfed:

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)

Ausnahme, wenn a nicht leer ist, aber b leer ist
Dan Osipov

1

APL (32)

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

Erläuterung:

{⍺⍵∊⍨⊂⍬                               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 Bytes

Der Algorithmus endet in n + 1Iterationen, wobei ndie Länge der kürzesten Liste in der Eingabe ist.

(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

Python - 69 Bytes

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

Wenn die Reihenfolge von Eingabe und Ausgabe absteigend wäre, könnte dies auf 61 Byte verkürzt werden :

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

Und weiter bis zu 45 Bytes, wenn Generatoren erlaubt sind:

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

Dies ist definitiv nicht O (n). .pop (0) und + = sind beide O (n) Operationen, die Sie O (n) Mal ausführen.
Isaacg

Ich wusste bis jetzt nicht einmal, dass Listen nicht als Listen in Python implementiert sind und auch dann pop(0)in O (1) +=implementiert werden können und zumindest besser als O (n) implementiert werden können (siehe den Link). Übrigens, Ihre Lösung verwendet +=(dh appendund extend) so oft wie meine. Wie auch immer, all das ist eine Implementierungsfrage (soweit ich weiß), also ist meine Funktion in einer (fiktiven) Python-Implementierung, in der Listen als Listen implementiert werden, O (n). Schließlich musste bei Ihrer Frage der Algorithmus O (n) sein, und meiner ist.
Wrzlprmft

Tatsächlich sind Anhängen und Erweitern in Python anders implementiert als + = ist. + = erstellt eine neue Liste, während .append und .extend eine vorhandene Liste ändern.
Isaacg

0

Perl 6: 53 Zeichen

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

Verschieben Sie den Wert von aoder bmit dem kleineren Wert, bis aXOR b( a^b) wahr ist. Geben Sie dann alles zurück, was noch übrig ist, und reduzieren Sie []die Arrays in der Liste ( a[],b[]).

Unter der Annahme, dass die Verschiebung vom Anfang eines Arrays an O (n) ist, sind zwei Vergleiche und eine Verschiebung pro Element der schlimmste Fall, sodass der Algorithmus O (n) ist.


0

JavaScript (ES5) 90 86 90 Bytes

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

edit: (90 -> 86) Verschob den Ternären in die for-Schleifenbedingung. Idee von Dennis gestohlen.

edit: (86 -> 90) Die Umwandlung von Array in String wurde entfernt, da das O (n) gebrochen wird -Anforderung verletzt.


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)

Eingang:

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

Ausgabe:

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

Ungolfed:

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
)

Könnte es wahrscheinlich besser machen.


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

0

R 80

Gleiche Lösung wie in Scala und anderen Sprachen. Ich bin mir nicht so sicher, ob x [-1] O (1) ist.

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

Mathematica, 104 Bytes

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

Anonymous-Funktion, speichert die Länge der beiden Eingabelisten in den Variablen mund ndann ist jede Iteration der DoSchleife Sowein Element einer der Listen, die den Zähler für diese Liste erhöhen ( ifür die erste,k für die zweite) um eins wird. Wenn einer der Zähler die Länge der Liste überschreitet, wird die IfAnweisung immer Sowdas Element aus der anderen Liste sein. Nach der n+mOperation sind alle Elemente erledigt.Reapoder vielmehr [[2,1]]ist ein Teil seiner Ausgabe eine Liste von Elementen in der Reihenfolge, in der sie warenSow n waren.

Ich bin mir der Interna nicht sicher (greift auf einen Teil einer Liste zu) O(1) Operation oder nicht), aber die Timings auf meinem Computer sahen in Bezug auf die Länge der eingegebenen Liste recht linear aus.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.