Лучший алгоритм для выполнения альтернативной сортировки массива с помощью javascript?

Следующий вопрос был моим вопросом. Но я не мог взломать его и даже не мог подумать, как это сделать.

var arr = [1,4,5,8,3,2,6,9,7,10];

Ожидаемый результат альтернативной сортировки:

[10,1,9,2,8,3,7,4,6,5]

То, что я пробовал:
Я попробовал нарезать Math.max.apply(null, arr) и Math.min.apply(null, arr), чтобы вставить отдельный пустой массив. Но было сказано, что алгоритм не является оптимальным.

Ответы

Ответ 1

Вот один из способов сделать это:

var arr = [1, 4, 5, 8, 3, 2, 6, 9, 7, 10];

// Sort the source array
arr.sort((a, b) => a - b);

// This will be the final result
var result = [];

// Create two pointers
var a = 0,
  b = arr.length - 1;

while (result.length < arr.length) {
  // Push the elements from start and end to the result array
  result.push(arr[b]);

  // Avoid bug when array is odd lengthed
  if (a !== b) {
    result.push(arr[a]);
  }

  a++;
  b--;
}

console.log(result);

Ответ 2

Я бы отсортировал массив, а затем повторил его, выбирая значения с начала и конца (inloop расчетные смещения) на каждой итерации. Окончательная проверка на нечетные массивы завершила бы процесс.

let a = [1, 4, 5, 8, 3, 2, 6, 9, 7, 10];
a.sort((a, b) => a - b);
let b =[];
    
let l = a.length-1;  // micro optimization
let L = l/2;         // micro optimization
for(var i=0; i<L; i++) b.push( a[l-i] ,a[i] );
if(a.length%2) b.push( a[i] ); // add last item in odd arrays

console.log(b);

Ответ 3

Если вы предположите, что массив будет набором последовательных чисел (хороший вопрос, чтобы спросить о данных), вы можете сделать это очень быстро, без необходимости сортировать или мутировать исходный массив (например, O (n)):

var arr = [1, 4, 5, 8, 3, 2, 6, 9, 7, 10];

let a = arr.reduce((a, c, i) => {
  a[c > arr.length >> 1 ? (arr.length - c) << 1 : (c << 1) - 1] = c
  return a
}, [])
console.log(a)

Ответ 4

Здесь мой ответ, основанный на интуиции, которую вы берете с фронта, а затем назад, повторно из отсортированного массива, пока не станет пустым. Трюк избегает "max" и "min", которые оценивают весь массив и просто сортируют его один раз.

Многие из других ответов помещают неопределенный в массив, если исходный массив имеет нечетную длину. Я бы оставил комментарий по этим вопросам, но у меня нет репутации. Вот почему я ограничиваю проверку дважды за цикл.

var arr = [1,4,5,8,3,2,6,9,7,10];
// Sort numerically (not lexicographically)
arr.sort((a, b) => a - b)
// The output array
var out = []
// Take from the front, then back until original array is empty
while (true) {
  if (arr.length == 0) break
  out.push(arr.pop())
  if (arr.length == 0) break
  out.push(arr.shift())
}
// Output answer
console.log(out)

Ответ 5

Мое решение для удобочитаемости/скрытой магии:

// Input
var arr = [1,4,5,8,3,2,6,9,7,10];

// Sort
var arr1 = arr.sort((a,b) => (a - b));

// Compose
var arr2 = [];
for (var i = 0; i < arr1.length; i++) {
  arr2.push(arr1[(i % 2) === 0 
    ? arr1.length-1-(i/2)   // get from end half
    : (i-1)/2               // get from begin half
  ])
}

// Output
console.log(arr2); // = [10, 1, 9, 2, 8, 3, 7, 4, 6, 5] 

Ответ 6

Альтернативный метод с добавлением только одной переменной:

var arr = [1, 4, 5, 8, 3, 2, 6, 9, 7, 10];

arr = arr.sort((a, b) => b - a);

var result = [];

var a = 0;
while (result.length < arr.length) {
    result.push(arr[a]);
    result.push(arr[arr.length - a - 1]);
    a++;
}

console.log(result);

Ответ 7

var a = [1,4,5,8,3,2,6,9,7,10];
var b = a.sort((a, b) => a - b);
var c = a.sort((a, b) => a - b).reverse();
var d = [];

let e = a.length-1;
let f = e/2;

for(let i=0; i<f; i++)  d.push( b.pop(), c.pop() );

Замените b и c в цикле for на функции для проверки:

for(let i=0; i<f; i++) d.push( a.sort((a, b) => a - b).pop(), a.sort((a, b) => a - b).reverse().pop() );

Ответ 8

sort массив и разделите на две части, теперь используйте сокращение, чтобы поместить элементы из двух массивов

//original array
var arr = [1, 4, 5, 8, 3, 2, 6, 9, 7, 10];
//sorting origina array in ascending order
var m = arr.sort(function(a, b) {
  return a - b;
});

// diving the sorted array in two parts
let getFirstSet = m.splice(0, arr.length / 2);
// now m containleft over items after the splice
// again sorted it in descending order to avoid back looping
let getSecondSet = m.sort(function(a, b) {
  return b - a;
});

//using reduce function
let newArray = getFirstSet.reduce(function(acc, curr, index) {
  // pushing element from second array containing 10,9,8,7,6
  acc.push(getSecondSet[index]);
  // pushing element from first array containing 1,2,3,4,5
  acc.push(getFirstSet[index]);
  return acc;
}, []); // [] is the initial array where elements will be pushed

console.log(newArray)

Ответ 9

Другой альтернативный взгляд... если этот фанковый сорт будет сделан на месте, например .sort?

let input = [1, 4, 5, 8, 3, 2, 6, 9, 7, 10];
input.sort((a, b) => b - a).every((n, i, a) => (a.splice((i * 2 + 1), 0, a.pop()), (i * 2) < a.length));
console.log(input);

Ответ 10

Вот быстрое решение, использующее тройные операторы и оператор modulo для переключения.

let arr = [1, 4, 5, 8, 3, 2, 6, 9, 7, 10];
let j = 0;
let k = arr.length - 1;

// sort array
arr.sort((a, b) => a - b);

let new_array = [];
for (let i in arr) {
  new_array[i] = i % 2 == 0 ? arr[k--] : arr[j++];
}
// prints array
console.log(new_array);