在JavaScript中高效计算Josephus排列

这个问题的名字可以说是古代历史学家约瑟夫斯一生中最重要的事件-根据他的故事,他和他的40名士兵在一次围攻中被罗马人困在一个山洞里。

他们拒绝屈服于敌人,转而选择了集体自杀-他们围成一个圈,每三人杀了一个人,直到最后一个人被留下为止(并且应该自杀以结束行动) )。

约瑟夫(Josephus)和另一个男人是最后两个,我们现在知道故事的每个细节,您可能已经正确地猜想他们没有完全遵循最初的想法。

我们需要编写一个返回约瑟夫斯排列的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
]