Fusionner deux listes triées

14

Tri par fusion

Dans ce défi, vous allez implémenter le sous-programme de fusion de tri par fusion. Plus précisément, vous devez créer une fonction ou un programme ou un verbe ou similaire qui prend deux listes, chacune triée par ordre croissant, et les combine en une liste triée par ordre croissant. Exigences:

- Votre algorithme doit prendre un temps asymptotiquement linéaire dans la taille de l'entrée. Veuillez cesser de donner des solutions O (n ^ 2).

  • Vous ne pouvez pas utiliser de fonctions intégrées capables de trier une liste, ou de fusionner une liste, ou quelque chose comme ça. Discrétion de l'auteur.
  • Le code doit être capable de gérer des éléments répétés.
  • Ne vous inquiétez pas des listes vides.

Exemples:

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]

Il s'agit de , alors que le code le plus court gagne!

isaacg
la source
Faut-il gérer des éléments répétés dans une liste, ou seulement entre les deux listes?
Keith Randall
Disons les deux. L'idée est que vous devriez pouvoir l'utiliser pour effectuer un tri par fusion.
isaacg
Est-il casher de gâcher les tableaux d'entrée?
skibrianski
3
Je ne sais pas comment interpréter l' algorithme doit prendre un temps asymptotiquement linéaire . Les algorithmes ne prennent pas de temps, les implémentations le font. Le temps d'exécution de ma réponse Golfscript est O (effrayant) avec l'interpréteur Ruby, mais le testeur de golf en ligne se comporte beaucoup mieux et pourrait en fait être linéaire (cependant, aucun moyen réel de dire sans le code source). Mon point est: b=a;b=b.lengthpourrait dupliquer le tableau entier a(et entraîner un temps O (n ^ 2) s'il est exécuté pour chaque élément) ou dupliquer uniquement la référence au tableau (temps O (n)). Lequel compte?
Dennis
1
Je suppose que dans des cas comme ceux-ci, faites de votre mieux pour le comprendre, mais si vous ne pouvez vraiment pas le dire, vous pouvez supposer que les choses fonctionnent bien, comme la deuxième alternative que vous avez mentionnée. Vous pouvez supposer que l'interprète fonctionne bien si votre langue n'a pas d'interprète standard.
isaacg

Réponses:

8

Rebmu ( 35 32 caractères)

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

Tester

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

Sur

Rebmu est un dialecte de Rebol qui permet de «mushing» de code régulier pour les situations qui nécessitent de la brièveté. Insensible, le code fonctionne un peu comme:

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)

Je crois que cela satisfait l' exigence O (n) car le bloc jusqu'à est au plus en boucle autant de fois que la longueur de l'entrée (et le reverseseul change l'ordre du conteneur des blocs d'entrée, pas les blocs eux-mêmes). L'utilisation takeest peut-être une liberté, mais reste un impact d'efficacité mineur.

Rebol ( 83 75 caractères)

Un tout petit peu différent: dans Rebol, les chemins sont une expression plus courte que firstou second. aest le bloc d'entrée contenant les deux blocs:

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

Solutions 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 101 99 93

Merci à @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
la source
1
Vous pouvez écrire a%b=a++baprès la correspondance du motif principal pour gérer les listes vides, ce qui supprimera quelques caractères.
swish
la solution Haskell n'échoue-t-elle pas si la première liste manque d'abord de contenu?
John Dvorak
Si vous regardez la première fonction, elle appelle récursivement la fonction avec la liste raccourcie comme deuxième argument et la liste allongée comme premier argument, ou bien échange les arguments. Par conséquent, le premier argument n'est jamais plus court. Étant donné que l'OP ne démarre pas vide, il ne se vide jamais.
isaacg
4

Python (79)

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

Python (95, si nous ne sommes pas autorisés à retourner un générateur)

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

Itertools est la solution à tous les problèmes du monde.

Bonus: les deux fonctionnent sur un nombre arbitraire de listes et s'inquiètent des listes vides (comme dans, ils prendront avec plaisir 2 listes vides et retourneront une liste vide, ou prendront 1 liste vide et 1 liste non vide, et ils renverront celui qui n'est pas vide. Une autre fonctionnalité ajoutée des 2 non-cédés: ils s'exécuteront également sans argument, et retourneront simplement une liste vide.)

Non golfé:

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
la source
Dans vos solutions sans générateur, utilisez à la r+=[...]place de r.append(...)(enregistre 4 caractères à chaque fois)
hlt
Je ne veux pas vous offenser par cela, mais si votre réponse contient du code dans une langue qui est juste une autre langue avec des modifications apportées spécifiquement pour le golf, je vais le déprécier. C'est dommage, les vraies réponses en python sont bonnes.
undergroundmonorail
Si vous les divisez en différents articles, je voterai pour celui en python.
undergroundmonorail
4
@undergroundmonorail Votez-vous contre toutes les réponses GolfScript?
Evpok
1
@Evpok Maintenant que vous le mentionnez, autant le jeter sur la méta et voir ce qu'ils ont à dire là-bas.
ɐɔıʇǝɥʇuʎs
3

C - 75

Cela fonctionne sur des NULLtableaux terminés de int *, bien que cela fonctionnerait aussi bien pour les pointeurs vers d'autres types en substituant la fonction de comparaison appropriée **b < **a(par exemple, strcmp(*b, *a) < 0).

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

Non golfé:

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

Golfscript, 29 27 30 29 26 octets

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

ou

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

Comment ça fonctionne

La commande

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

sera traité comme suit:

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

La sortie est:

[1 2 3 4]
Dennis
la source
La duplication des tableaux dans la pile en fait-elle O (n ^ 2)?
swish
@swish: Je ne suis pas informaticien, mais je dirais que cela dépend de l'implémentation. Si l'interpréteur duplique réellement l'ensemble des tableaux, je suppose que c'est le cas.
Dennis
La version précédente était O (n ^ 2) pour des tableaux très similaires (par exemple, [1 1 1 ... 2]et [1 1 1 ... 3]), car comparer les tableaux (plutôt que leurs premiers éléments) serait très lent dans ce cas.
Dennis
Les seules opérations de tableau qui ont lieu dans la nouvelle version sont la duplication, l'échange et la rotation sur la pile. Étant donné que les tableaux dupliqués ne sont utilisés que pour extraire des éléments uniques et tester les tableaux pour la non-vacuité (les deux opérations destructrices dans Golfscript), le code ci-dessus peut être exécuté en temps O (n) (en dupliquant, échangeant et faisant pivoter les références à la tableaux). Les performances réelles dépendent de l'interpréteur.
Dennis
2

J - 42 33

Version modifiée d' ici + le commentaire de @algorithmshark

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

kajoute la tête du tableau de droite aux queues fusionnées des deux tableaux. k~est le même, mais avec des tableaux inversés. (>&{.)compare les têtes. Le code générera une erreur si l'un des tableaux est vide, dans ce cas, nous renvoyons uniquement leur concaténation ,.

bruissement
la source
Je suppose que puisque /:~ a,bc'est la réponse interdite (avec [:/:~,), que vous visez la réponse la plus courte qui ne comprend pas /:, non?
Dane
Je ferai remarquer que la question dit: «Ne vous inquiétez pas des listes vides».
Dane
@Dane Le test de vide requis pour que la récursivité s'arrête.
swish
m=:k~`k@.(>&{.)`,@.(0=*&#)enregistre 2 car.
algorithmshark
En fait, vous pouvez obtenir le tout à 33 caractères: k=:(m}.),~0{]et m=:k~`k@.(>&{.) ::,. Nous utilisons 0{pour lancer une erreur lorsque la liste est vide, puis intercepter cette erreur et quitter avec ,.
algorithmshark
2

JavaScript (ES6), 69 79 octets

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

Comment ça fonctionne

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
la source
La comparaison des tableaux avec l' <opérateur n'est pas valide car elle fait une comparaison de chaînes:f([123, 456, 789], [1, 2, 3, 4, 5]) => [1, 123, 2, 3, 4, 456, 5, 789]
nderscore
@nderscore: D'accord. Cela n'aurait pas fonctionné de toute façon, car la comparaison de l'ensemble des tableaux pourrait ne pas être O (n). La même chose semble être vraie pour le test de non-vide, qui doit convertir l'ensemble du tableau en chaîne.
Dennis
Ouais, je ne sais pas quel est le big-o pour la conversion de type chaîne-> chaîne.
nderscore
1
Concaténer un tableau avec []puis le convertir en chaîne nécessite O (n) de temps. Le faire une fois pour tous les n éléments du tableau prend O (n ^ 2) temps.
Dennis
Logique. Je l'ai.
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)

J'ai écrit ceci avant de voir les commentaires d'OP sur les temps d'exécution d'autres réponses, c'est donc une autre solution qui est O (n) dans l'algorithme mais pas la mise en œuvre.

xnor
la source
Quels algorithmes ont des extraits du devant des tableaux comme O (1)? Quels algorithmes les comparaisons de listes prennent-elles O (1)? Vous pouvez également
jouer au
@isaacg Shoot, j'avais oublié les répétitions qui faisaient peut-être la comparaison de liste O (n). J'ai donc supprimé cette optimisation pour 6 autres personnages. Vous pouvez extraire et ajouter à l'avant dans O (1) dans une liste chaînée. Je ne vois pas comment vous pouvez faire ... et ... ou ... jouer bien avec le retour de la valeur.
xnor
OK, je vois maintenant comment faire ... et ... ou ..., mais cela ne sauvegarde pas les caractères en raison des parens nécessaires. return[a.pop(0)]+(a and m(a,b)or b)
xnor
@isaacg: Pour extraire le devant d'un tableau dans O (1), augmentez simplement le pointeur du tableau de sorte qu'il pointe vers le deuxième élément et libérez la mémoire consommée par le premier élément.
Wrzlprmft
@Wrzlprmft Je n'ai pas pu faire fonctionner l'astuce du tableau car les deux éléments du tableau sont évalués quelle que soit la valeur booléenne, ce qui génère une erreur lorsque a est la liste vide. Existe-t-il un moyen rapide de créer un "tableau paresseux"?
xnor
2

Haskell, 35 octets

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

Haskell, 30 octets (non concurrent)

Cette version non concurrente ne garantit que l'exécution linéaire si aet bont des éléments disjoints; sinon, il fonctionne toujours correctement mais peut utiliser le temps quadratique.

a#b|a<b=b#a|c:d<-b=c:a#d
a#_=a
Anders Kaseorg
la source
2

PHP 91 98 91 octets

edit # 1: Vide $bnécessite une condition supplémentaire dans les accolades (+7).
modifier # 2: golfs mineurs
modifier # 3: ajouté une deuxième version

assez simple. La plus belle partie est le ternaire à l'intérieur du array_shift
(qui échoue si vous l'essayez sans les curlys)

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

ou

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

non golfé

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

tester

$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>';
Titus
la source
Je ne pouvais pas comprendre pourquoi vous ne rendez pas les choses simples $a&(!$b|$a[0]<$b[0])?$a:$bau lieu de${$a&(!$b|$a[0]<$b[0])?a:b}
Jörg Hülsermann
1
@ JörgHülsermann Le array_shiftparamètre est utilisé par référence. Ce doit être une variable; une expression ne fonctionnera pas.
Titus
1

Aller, 124 caractères

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

Même type d'approche que les PO.

Mat
la source
1

perl, 87 caractères / perl 5.14, 78 + 1 = 79 caractères

Cette implémentation encombre les références de tableau d'entrée. En dehors de cela, c'est assez simple: alors que les deux tableaux ont quelque chose, désactivez le bas des deux. Retournez ensuite le bit fusionné joint à tous les bits restants (il ne restera qu'un seul parmi @ $ x ou @ $ y). Perl5 droit, 87 caractères:

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

En utilisant Perl 5.14.0 et son nouveau décalage de référence de tableau: 78 caractères + 1 pénalité de caractère = 79 caractères:

sub M{($x,$y,@o)=@_;push@o,shift($$x[0]>$$y[0]?$y:$x)while@$x&&@$y;@o,@$x,@$y}
skibrianski
la source
*au lieu d' &&enregistrer un octet. Et encore plus sisub M{map{shift(!@$x+@$y*($$y[0]<$$x[0])?$y:$x)}map@$_,($x,$y)=@_}
user2846289
@VadimR, wow. bon travail. Allez-y et postez cela si vous le souhaitez - je n'aurais jamais pensé faire le tour de double carte au lieu de pousser sur un tableau.
skibrianski
1

Java: 144

C'est assez simple. Une fonction qui prend deux tableaux et renvoie un, la version fusionnée, golfée et sans wrapper de compilation:

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

Non golfé (avec un wrapper compilable et exécutable):

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

Exemples d'exécutions:

$ 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

Tout conseil à raccourcir serait apprécié.

ProgrammerDan
la source
1

Scala, 97 octets

Solution récursive avec O (n). Pour raccourcir le code, une opération est parfois effectuée en commutant les 2 paramètres interchangeables, c'est-à-dire que f (a, b) appelle 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)

Non golfé:

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
la source
Exception si a n'est pas vide, mais b est vide
Dan Osipov
1

APL (32)

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

Explication:

{⍺⍵∊⍨⊂⍬                               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
la source
1

LISP, 117 octets

L'algorithme se termine par des n + 1itérations, où nest la longueur de la liste la plus courte en entrée.

(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
la source
0

PYG (50)

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

PYG (64, encore une fois, si aucun générateur n'est autorisé.):

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

Une adaptation de ma réponse Python .

ɐɔıʇǝɥʇuʎs
la source
0

Python - 69 octets

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

Si l'ordre d'entrée et de sortie décroissait, cela pourrait être raccourci à 61 octets :

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

Et plus loin jusqu'à 45 octets si les générateurs sont autorisés:

def m(A,B):
    while A+B:yield[A,B][A<B].pop(0)
Wrzlprmft
la source
Ce n'est certainement pas O (n). .pop (0) et + = sont tous deux des opérations O (n) que vous effectuez O (n) fois.
isaacg
Je ne savais même pas jusqu'à présent que les listes ne sont pas implémentées en tant que listes en Python et même alors pop(0)peuvent être implémentées dans O (1) et +=peuvent au moins être implémentées mieux que O (n) (voir le lien). Soit dit en passant, votre solution utilise +=(c'est-à-dire appendet extend) aussi souvent que la mienne. Quoi qu'il en soit, tout cela est une question d'implémentation (pour autant que je sache), donc dans une implémentation (fictive) de Python, où les listes sont implémentées comme des listes, ma fonction est O (n). Enfin, votre question exigeait que l' algorithme soit O (n), et le mien l'est.
Wrzlprmft
En fait, ajouter et étendre sont implémentés différemment en python que + = est. + = crée une nouvelle liste, tandis que .append et .extend modifient une liste existante.
isaacg
0

Perl 6:53 caractères

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

Passez de la valeur la plus petite aou bla plus petite jusqu'à ce que aXOR b( a^b) soit vrai. Retournez ensuite tout ce qui reste, flattening ( []) les tableaux dans la liste ( a[],b[]).

En supposant que le décalage depuis le début d'un tableau est O (n), le pire des cas est deux comparaisons et un décalage par élément, donc l'algorithme est O (n).

Mouq
la source
0

JavaScript (ES5) 90 86 90 octets

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) Déplacement du ternaire dans la condition de boucle for. Idée volée à Dennis.

edit: (86 -> 90) Suppression du tableau en chaîne, car cela rompt l' exigence O (n) .

nderscore
la source
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)

Contribution:

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

Production:

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

Non golfé:

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
)

Pourrait probablement faire mieux.

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

R, 80

Même solution que dans Scala et dans d'autres langues. Je ne suis pas sûr que x [-1] soit 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
la source
0

Mathematica, 104 octets

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

Fonction anonyme, stocke la longueur des deux listes d'entrée dans les variables mpuis n, à chaque itération de la Doboucle, Sowun élément de l'une des listes incrémentant le compteur de cette liste ( ipour la première, kpour la seconde) d'une unité . Si l'un des compteurs dépasse la longueur de la liste, l' Ifinstruction sera toujours Sowl'élément de l'autre liste. Après les n+mopérations, tous les éléments ont été pris en charge. Reapou plutôt une partie [[2,1]]de sa sortie est une liste d'éléments dans l'ordre où ils ont étéSow n.

Je ne suis pas sûr des internes (accède à une partie d'une liste, une O(1)opération ou non), mais les délais semblaient assez linéaires sur ma machine en ce qui concerne la longueur de la liste d'entrée.

LLlAMnYP
la source