【发布时间】:2019-11-05 13:24:05
【问题描述】:
在训练代码战时,我遇到了关于约瑟夫排列的挑战,我尝试先在纸上解决它,然后再将其转换为代码。
问题如下: “创建一个返回 Josephus 排列的函数,将要排列的项目的初始数组/列表作为参数,就好像它们在一个圆圈中一样,并计算每 k 个位置,直到没有剩余。”
我的主要想法是:
- 有一个辅助数组来保持响应
-
使用两个迭代器:
- i:跟踪给定数组中的当前索引
- k:跟踪排列的步骤
在 0 处初始化 i,在 1 处初始化 k
- 当原始数组只剩下一个元素时:
- 将元素推送到输出数组
- 只要 i 不是数组的最后一个索引:
- 如果 k = 步长:
- 从原数组中取出元素,推入输出数组,最后替换k = 1
- 如果 k != 步骤:
- 增加 i 和 k
- 如果 k = 步长:
- 当 i 是原始数组的最后一个索引时(并且该数组有多个元素):
- 如果 k = 步长:
- 从原数组中取出元素,压入输出数组,替换k = 1,设置i = 0
- 如果 k != 步骤:
- 设置 i = 0 并递增 k
- 如果 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() 很慢,这是我的一种可能(错误的数据结构)
建议查看递归(这更让我怀疑算法)。不过,我并没有真正了解如何进行递归。
提前感谢您的帮助!
【问题讨论】:
-
不知道codereview,会去看看。我正在寻找替代方案,但没有想到递归。
-
splice往往很昂贵,但我无法想象您提供的测试可能会持续 12 秒,除非您的代码中的某些循环卡住或设置为在非凡数量后完成重复次数。 -
@גלעד ברקן:如果我没记错的话,CodeWars 为您提供了一些示例测试用例,以便您测试算法的正确性,但隐藏了其他用于确保运行时效率的示例。
标签: javascript arrays algorithm permutation josephus