高效计算约瑟夫排列 (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 ]
广告