高效计算约瑟夫排列 (JavaScript)


这个问题的名字来源于古史学家约瑟夫斯生命中最重要的事情——根据他的故事,他和他的40名士兵在围攻期间被罗马人困在一个山洞里。

他们拒绝向敌人投降,而是选择集体自杀,但方式有所不同——他们围成一个圆圈,每隔三个人就杀死一个人,直到只剩下一个人(然后这个人应该自杀以结束这场行动)。

约瑟夫斯和另一个人是最后两个人,正如我们现在所知道的这个故事的所有细节一样,你可能已经猜到他们并没有完全按照最初的想法去做。

我们需要编写一个 JavaScript 函数来返回约瑟夫排列。

将要排列的初始数组/列表作为参数,就像它们在一个圆圈中一样,每隔 k 个位置就数出一个,直到没有剩余为止。

例如,当 n=7 且 k=3 时,josephus(7,3) 应该这样运行。

[1,2,3,4,5,6,7] − initial sequence
[1,2,4,5,6,7] => 3 is counted out and goes into the result [3]
[1,2,4,5,7] => 6 is counted out and goes into the result [3,6]
[1,4,5,7] => 2 is counted out and goes into the result [3,6,2]
[1,4,5] => 7 is counted out and goes into the result [3,6,2,7]
[1,4] => 5 is counted out and goes into the result [3,6,2,7,5]
[4] => 1 is counted out and goes into the result [3,6,2,7,5,1]
[] => 4 is counted out and goes into the result [3,6,2,7,5,1,4]

因此,我们的最终结果是:

josephus([1,2,3,4,5,6,7],3)==[3,6,2,7,5,1,4];

示例

代码如下:

const arr = [1, 2, 3, 4, 5, 6, 7];
const num = 3;
const helper = (n, k, i, map) => {
   if (map.hasOwnProperty([n, k, i]))
   return map[[n, k, i]];
   if (i === 1)
   return map[[n, k, i]] = (k − 1) % n;
   return map[[n, k, i]] =
   (k + helper(n − 1, k, i − 1, map)) % n;
}
const josephus = (arr, k) => {
   let n = arr.length;
   let result = new Array(n);
   let map = {};
   for (let i=1; i<=n; i++)
   result[i − 1] = arr[ helper(n, k, i, map) ];
   return result;
};
console.log(josephus(arr, num));

输出

控制台输出:

[
   3, 6, 2, 7,
   5, 1, 4
]

更新于:2020年11月21日

273 次浏览

开启您的职业生涯

完成课程获得认证

开始学习
广告