使用 JavaScript 高效计算约瑟夫斯排列

javascriptweb developmentfront end technologyobject oriented programming

该问题的名称来源于古代历史学家约瑟夫斯一生中最重要的事件 − 根据他的故事,他和他的 40 名士兵在一次围攻中被罗马人困在一个山洞里。

他们拒绝向敌人投降,而是选择集体自杀,但结局却有所不同 −他们围成一圈,每三个人杀一个人,直到剩下最后一个人(而且应该自杀来结束这一行为)。

约瑟夫和另一个人是最后两个人,由于我们现在知道了故事的每一个细节,你可能已经猜到了他们并没有完全按照原来的想法去做。

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

将要排列的初始数组/项目列表作为参数,就好像它们在一个圆圈里,每 k 个位置计数一次,直到没有剩余的元素。

例如,当 n=7 和 k=3 时,josephus(7,3) 应该这样做。

[1,2,3,4,5,6,7] − 初始序列
[1,2,4,5,6,7] => 3 被算出并计入结果 [3]
[1,2,4,5,7] => 6 被算出并计入结果 [3,6]
[1,4,5,7] => 2 被算出并计入结果 [3,6,2]
[1,4,5] => 7 被算出并计入结果 [3,6,2,7]
[1,4] => 5 被算出并计入结果 [3,6,2,7,5]
[4] => 1 被算出并计入结果 [3,6,2,7,5,1]
[] => 4 被算出并计入结果 [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
]

相关文章