Во время обучения кодовым войнам я столкнулся с проблемой перестановок Джозефа, сначала я попытался решить ее на бумаге, а затем перевести в код.
Проблема заключается в следующем:
«Создайте функцию, которая возвращает перестановку Джозефуса, принимая в качестве параметров исходный массив / список элементов, подлежащих перестановке, как если бы они были в круге, и отсчитывал каждые k мест, пока не осталось ни одного».
Моя главная идея была:
function josephus(items,step){
var output = [];
var i = 0;
var k = 1;
if( items == [] ) {
return [];
}
while (items.length != 1) {
if (k == step && i == items.length - 1) {
output.push(items[i]);
items.splice(i, 1);
i = 0;
k = 1;
} else if (k == step && i != items.length - 1) {
output.push(items[i]);
items.splice(i, 1);
k = 1
} else if (k < step && i == items.length - 1) {
k++;
i=0;
} else if (k < step && i != items.length - 1) {
k++;
i++;
}
}
output.push(items[0]);
return output;
}
Это работает, но неэффективно, когда я запускаю его на тестовых прогонах, я получаю, что 5 тестовых тестов пройдены, но он также включает STDERR: Тайм-аут выполнения (12000 мс).
Ниже приведены примеры испытаний:
Test.assertSimilar(josephus([1,2,3,4,5,6,7,8,9,10],1),[1,2,3,4,5,6,7,8,9,10])
Test.assertSimilar(josephus([1,2,3,4,5,6,7,8,9,10],2),[2, 4, 6, 8, 10, 3, 7, 1, 9, 5])
Test.assertSimilar(josephus(["C","o","d","e","W","a","r","s"],4),['e', 's', 'W', 'o', 'C', 'd', 'r', 'a'])
Test.assertSimilar(josephus([1,2,3,4,5,6,7],3),[3, 6, 2, 7, 5, 1, 4])
Test.assertSimilar(josephus([],3),[])
Мой вопрос: как я могу сделать это более эффективным?
Это неправильный алгоритм, который я использую, или его реализация?
В комментарии упоминаются две вещи:
push () очень медленный, что было одной из моих возможностей (неправильная структура данных)
предложил посмотреть на рекурсию (что больше относится к моим сомнениям в алгоритме). Хотя я не вижу, как сделать это рекурсивным.
Заранее спасибо за помощь!