Объединить два отсортированных списка

14

Сортировка слиянием

В этой задаче вы реализуете функцию слияния сортировки слиянием. В частности, вы должны создать функцию или программу или глагол или аналог, который берет два списка, каждый из которых отсортирован в порядке возрастания, и объединяет их в один список, отсортированный в порядке возрастания. Требования:

- Ваш алгоритм должен занимать асимптотически линейное количество времени в размере ввода. Пожалуйста, прекратите давать O (n ^ 2) решения.

  • Вы не можете использовать какие-либо встроенные функции, способные сортировать список, объединять список или что-то в этом роде. Авторское усмотрение.
  • Код должен быть в состоянии обрабатывать повторяющиеся элементы.
  • Не беспокойтесь о пустых списках.

Примеры:

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]

Это , поэтому победит самый короткий код!

isaacg
источник
Нужно ли обрабатывать повторяющиеся элементы в списке или только между двумя списками?
Кит Рэндалл,
Давайте скажем оба. Идея состоит в том, чтобы вы могли использовать это для сортировки слиянием.
Исаак
Кошерно засорять входные массивы?
Скибрянски
3
Я не уверен, как интерпретировать алгоритм должен занимать асимптотически линейное количество времени . Алгоритмы не занимают время, реализации делают. Время выполнения моего ответа в Golfscript составляет O (страшно) с интерпретатором Ruby, но он- лайн тестер Golfscript ведет себя намного лучше и на самом деле может быть линейным (хотя без оригинального кода это невозможно). Моя точка зрения: b=a;b=b.lengthможет дублировать весь массив a(и привести к O (n ^ 2) времени, если выполняется для каждого элемента) или дублировать только ссылку на массив (O (n) времени). Какой из них считается?
Деннис
1
Я полагаю, что в таких случаях просто постарайтесь понять это, но если вы честно не можете сказать, вы можете предположить, что все работает хорошо, как вторая альтернатива, которую вы упомянули. Вы можете предположить, что переводчик работает хорошо, если на вашем языке нет стандартного переводчика.
Исаак

Ответы:

8

Ребму ( 35 32 символов)

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

Тестовое задание

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

Около

Rebmu - это диалект Rebol, который допускает «скопление» обычного кода в ситуациях, требующих краткости. Без кода код работает примерно так:

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)

Я полагаю, что это удовлетворяет требованию O (n), так как блок до не более чем зациклен столько раз, сколько длина ввода (иreverse только переключает порядок контейнера входных блоков, а не самих блоков). Использование take- это, пожалуй, свобода, но все еще незначительный удар по эффективности.

Ребол ( 83 75 символов)

Просто немного по-другому: в Rebol пути являются более коротким выражением, чем firstили second.aвходной блок, содержащий два блока:

until[if a/2/1 < a/1/1[reverse a]append o:[]take a/1 tail? a/1]append o a/2
rgchris
источник
5

Решения ОП:

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

Благодаря @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
источник
1
Вы можете написать a%b=a++bпосле сопоставления с основным шаблоном, чтобы обрабатывать пустые списки, что сбрит пару символов.
swish
Разве решение Haskell не дает сбой, если в первом списке заканчивается контент первым?
Джон Дворак
Если вы посмотрите на первую функцию, она рекурсивно вызывает функцию с укороченным списком в качестве второго аргумента и удлиненным списком в качестве первого аргумента, или же меняет местами аргументы. Поэтому первый аргумент никогда не становится короче. Поскольку с помощью OP он не начинается пустым, он никогда не будет пустым.
Исаак
4

Python (79)

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

Python (95, если нам не разрешено возвращать генератор)

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

Itertools - решение всех мирских проблем.

Бонус: оба из них работают с произвольным числом списков и ДЕЙСТВИТЕЛЬНО беспокоятся о пустых списках (например, они с радостью возьмут 2 пустых списка и вернут пустой список, или возьмут 1 пустой и 1 непустой список, и они возвратят непустой. Еще одна добавленная особенность 2 неубежденных: они также будут работать без аргументов и просто вернут пустой список.)

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
ɐɔıʇǝɥʇuʎs
источник
В ваших решениях без генератора используйте r+=[...]вместо r.append(...)(каждый раз сохраняет 4
символа
Я не имею в виду никакого оскорбления этим, но если ваш ответ содержит код на языке, который является просто другим языком с изменениями, сделанными специально для игры в гольф, я собираюсь понизить его. Обидно, настоящие ответы на python хорошие.
подземный
Если вы разделите их на разные посты, я добавлю комментарий к python.
подземный
4
@undergroundmonorail Вы отрицаете все ответы GolfScript?
Евпок
1
@Evpok Теперь, когда вы упомянули об этом, с тем же успехом можете бросить его в мету и посмотреть, что они там скажут.
Aprıʇǝɥʇuʎs
3

С - 75

Это работает с NULLзавершенными массивами int *, хотя будет одинаково хорошо работать для указателей на другие типы, заменяя соответствующую функцию сравнения **b < **a(например, strcmp(*b, *a) < 0).

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++;
}
laindir
источник
3

Golfscript, 29 27 30 29 26 байтов

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

или

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

Как это устроено

Команда

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

будет обработан следующим образом:

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

Выход:

[1 2 3 4]
Деннис
источник
Делает ли дублирование массивов в стеке это O (n ^ 2)?
swish
@swish: я не специалист по информатике, но я бы сказал, что это зависит от реализации. Если интерпретатор фактически дублирует все массивы, я думаю, что так и есть.
Деннис
Предыдущая версия была O (n ^ 2) для очень похожих массивов (например, [1 1 1 ... 2]и [1 1 1 ... 3]), поскольку сравнение массивов (а не их первых элементов) было бы очень медленным в этом случае.
Деннис
Единственные операции с массивами, которые происходят в новой версии, - это дублирование, замена и ротация в стеке. Поскольку дублированные массивы используются только для извлечения отдельных элементов и проверки массивов на незаполненность (обе деструктивные операции в Golfscript), приведенный выше код можно запустить за O (n) время (путем дублирования, замены и поворота ссылок на массивы). Фактическая производительность зависит от переводчика.
Деннис
2

J - 42 33

Модифицированная версия отсюда + комментарий @algorithmshark

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

kдобавляет заголовок правого массива к объединенным хвостам обоих массивов. k~то же самое, но с перевернутыми массивами. (>&{.)сравнивает головы. Код выдаст ошибку, если один из массивов пуст, в этом случае мы возвращаем только их конкатенацию ,.

рассекать
источник
Я предполагаю, что, поскольку /:~ a,bзапрещенный ответ (вместе с [:/:~,), что вы стреляете за самый короткий ответ, который не включает /:, верно?
датчанин
Я укажу, что вопрос гласит: «Не беспокойтесь о пустых списках».
датчанин
@Dane Тест на пустоту, необходимый для остановки рекурсии.
swish
m=:k~`k@.(>&{.)`,@.(0=*&#)экономит 2 символа
алгоритмистика
Фактически, вы можете получить все это до 33 символов: k=:(m}.),~0{]и m=:k~`k@.(>&{.) ::,. Мы используем, 0{чтобы выдать ошибку, когда список пуст, а затем перехватить эту ошибку и выйти с помощью ,.
алгоритмистика
2

JavaScript (ES6), 69 79 байт

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

Как это устроено

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'.
                               //
)
Деннис
источник
Сравнение массивов с <оператором недопустимо, так как выполняется сравнение строк:f([123, 456, 789], [1, 2, 3, 4, 5]) => [1, 123, 2, 3, 4, 456, 5, 789]
nderscore
@nderscore: верно. В любом случае это не сработало бы, так как сравнение целых массивов не могло бы быть O (n). То же самое можно сказать и о тесте не пустоты, который должен преобразовать весь массив в строку.
Деннис
Да, я не уверен, что такое big-o для преобразования типа array-> string.
nderscore
1
Конкатенация массива с []последующим преобразованием его в строку требует времени O (n). Один раз для всех n элементов массива требуется O (n ^ 2) времени.
Деннис
Имеет смысл. Понял.
nderscore
2

Питон (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)

Я написал это до того, как увидел комментарии OP о времени выполнения других ответов, так что это еще одно решение, которое в алгоритме использует O (n), но не его реализацию.

XNOR
источник
Какие алгоритмы имеют выдержки из фронта массивов как O (1)? Какие алгоритмы сравнения списков принимают O (1)? Кроме того, вы можете
сыграть в
@isaacg Стреляй, я забыл о повторениях, возможно, сравнив список O (n). Итак, я убрал эту оптимизацию еще для 6 персонажей. Вы можете извлечь и добавить в начало в O (1) в связанном списке. Я не понимаю, как вы можете заставить ... и ... или ... играть с возвратом значения.
xnor
Хорошо, теперь я вижу, как это сделать ... и ... или ..., но это не спасает персонажей из-за необходимых паренов. return[a.pop(0)]+(a and m(a,b)or b)
xnor
@isaacg: чтобы извлечь фронт массива в O (1), просто увеличьте указатель массива так, чтобы он указывал на второй элемент, и освободите память, занятую первым элементом.
Wrzlprmft
@Wrzlprmft Я не смог заставить трюк массива работать, потому что оба элемента массива вычисляются независимо от логического значения, которое выдает ошибку, когда a - пустой список. Есть ли короткий способ сделать "ленивый массив"?
xnor
2

Haskell, 35 байт

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

Haskell, 30 байт (не конкурирует)

Эта неконкурентная версия гарантирует только линейное время выполнения, если aи bимеют непересекающиеся элементы; в противном случае он по-прежнему работает правильно, но может использовать квадратичное время.

a#b|a<b=b#a|c:d<-b=c:a#d
a#_=a
Андерс Касеорг
источник
2

PHP 91 98 91 байт

edit # 1: Пусто $bтребует дополнительного условия в фигурных скобках (+7).
редактирование # 2: незначительные игры в гольф
редактирование # 3: добавлена ​​вторая версия

довольно прямо. Самая приятная часть - это троица внутри array_shift
(которая терпит неудачу, если вы попробуете это без фигурных)

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

или

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

тестовое задание

$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
источник
Я не мог понять, почему вы делаете это не просто $a&(!$b|$a[0]<$b[0])?$a:$bвместо${$a&(!$b|$a[0]<$b[0])?a:b}
Йорг Хюльсерманн
1
@ JörgHülsermann array_shiftПараметр используется для справки. Это должна быть переменная; выражение не сработает.
Тит
1

Go, 124 символа

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

Такой же подход, как и у ОП.

Matt
источник
1

perl, 87 символов / perl 5.14, 78 + 1 = 79 символов

Эта реализация забивает ссылки на входные массивы. Кроме этого, это довольно просто: хотя в обоих массивах есть что-то, сдвиньте нижнюю из двух. Затем верните объединенный бит, объединенный с любыми оставшимися битами (останется только один из @ $ x или @ $ y). Прямолинейный perl5, 87 символов:

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

Использование perl 5.14.0 и его новомодного сдвига массива: 78 символов + 1 штраф = 79 символов:

sub M{($x,$y,@o)=@_;push@o,shift($$x[0]>$$y[0]?$y:$x)while@$x&&@$y;@o,@$x,@$y}
skibrianski
источник
*вместо того, &&чтобы сохранить байт. И даже больше, еслиsub M{map{shift(!@$x+@$y*($$y[0]<$$x[0])?$y:$x)}map@$_,($x,$y)=@_}
user2846289
@VadimR, вау. хорошо сделано. Если хотите, опубликуйте, что я никогда бы не подумал сделать трюк с двойной картой вместо того, чтобы нажимать на массив.
Скибрянски
1

Ява: 144

Это довольно просто. Функция, которая берет два массива и возвращает один, объединенную версию, в гольф и без оболочки компиляции:

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 (с компилируемой и запускаемой оболочкой):

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

Пример исполнения:

$ 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

Любые советы по сокращению будут оценены.

ProgrammerDan
источник
1

Скала, 97 байт

Рекурсивное решение с O (n). Чтобы сократить код, иногда операция выполняется путем переключения 2 взаимозаменяемых параметров, то есть 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)

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)
lambruscoAcido
источник
Исключение, если a не пусто, но b пусто
Дан Осипов
1

APL (32)

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

Объяснение:

{⍺⍵∊⍨⊂⍬                               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 байт

Алгоритм заканчивается n + 1итерациями, где nдлина самого короткого списка на входе.

(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
источник
0

Python - 69 байт

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

Если бы порядок ввода и вывода был убывающим, это можно было бы сократить до 61 байта :

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

И далее до 45 байтов, если разрешены генераторы:

def m(A,B):
    while A+B:yield[A,B][A<B].pop(0)
Wrzlprmft
источник
Это определенно не O (n). .pop (0) и + = - это O (n) операций, которые вы выполняете O (n) раз.
Исаак
До сих пор я даже не знал, что списки не реализованы как списки в Python и даже тогда pop(0)могут быть реализованы в O (1) и, +=по крайней мере, могут быть реализованы лучше, чем O (n) (см. Ссылку). Кстати, ваше решение использует +=(т.е. appendи extend) так же часто, как и мое. В любом случае, все это вопрос реализации (насколько я знаю), поэтому в (вымышленной) реализации Python, где списки реализованы в виде списков, моя функция - O (n). Наконец, ваш вопрос требует, чтобы алгоритм был O (n), а мой -.
Wrzlprmft
На самом деле, добавление и расширение реализованы в python иначе, чем + = is. + = создает новый список, а .append и .extend изменяют существующий.
Исаак
0

Perl 6: 53 персонажа

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

Переход от какой из aили bимеет меньшее значение, до тех пор , aисключающее ИЛИ b( a^b) не верно. Затем верните все, что осталось, сглаживая ( []) массивы в списке (a[],b[] ).

Предполагая, что сдвиг от начала массива равен O (n), наихудший случай - два сравнения и один сдвиг на элемент, поэтому алгоритм - O (n).

Mouq
источник
0

JavaScript (ES5) 90 86 90 байт

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) Переместил троичный в условие цикла. Идея украдена у Дениса.

edit: (86 -> 90) Удалено приведение Array к String, поскольку оно нарушает требование O (n) .

nderscore
источник
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)

Входные данные:

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

Выход:

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

Возможно, может быть лучше.

kukac67
источник
m[a:{x___,y_},b:{___,z_}]:=If[y<z,b~m~a,{x}~m~b~Join~{y}];{}~m~b_=b;
алефальфа
0

R, 80

То же решение, что и в Scala и других языках. Я не уверен, что x [-1] - это 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
источник
0

Mathematica, 104 байта

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

Анонимная функция хранит длину двух входных списков в переменных, mа nзатем каждую итерациюDo цикла Sows элемент одного из списков, увеличивающий счетчик для этого списка ( iдля первого, kдля второго) на единицу. Если один из счетчиков превышает длину списка, Ifоператор всегда будет Sowэлементом из другого списка. После n+mопераций все элементы позаботились.Reapили скорее часть[[2,1]] его вывода представляет собой список элементов в том порядке, в котором они былиSow n.

Я не уверен во внутренних функциях (доступ к части списка - O(1)операция или нет), но время выглядело достаточно линейно на моей машине по отношению к длине списка ввода.

LLlAMnYP
источник