据说著名犹太历史学家Josephus有过以下的故事:在罗马人占领乔塔帕特后,39 个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被敌人抓到,于是决定了一个自杀方式,41个人排成一个圆圈,由第1个人开始报数,每报数到第3人该人就必须自杀,然后再由下一个重新报数,直到所有人都自杀身亡为止。然而Josephus 和他的朋友并不想遵从。首先从一个人开始,越过k-2个人(因为第一个人已经被越过),并杀掉第k个人。接着,再越过k-1个人,并杀掉第k个人。这个过程沿着圆圈一直进行,直到最终只剩下一个人留下,这个人就可以继续活着。问题是,给定了和,一开始要站在什么地方才能避免被处决。Josephus要他的朋友先假装遵从,他将朋友与自己安排在第16个与第31个位置,于是逃过了这场死亡游戏。
// 1.约瑟夫环问题
let arr = [1, 2, 3, 4, 5, 6, 7];
let size = 3;
josephRing(arr, size); // 栈和堆的概念
console.log(arr); // 栈和堆的概念
/**
* 从arr中每size步取出一个元素 直到取不出(<size) 约瑟夫环
* @param {*} newArr
* @param {*} size
*/
function josephRing(newArr, size) {
let i = 0; //i 退出的元素对应的下标
while (newArr.length >= size) { //还能取继续取
let temp = size, //临时变量 用于记录步长 size
flag = 0; //判断变量
while (true) {
if (temp-- == 1) { //找到第size个人 开始取
newArr.splice(i, 1); //具体取谁
flag = 1;
} else {
i++; //当取到时 i就不需要自增 没取到才自增
}
if (i == newArr.length) //取到最后又从第一个开始
i %= newArr.length;
if (flag == 1) { //取到了就退出
flag = 0;
break;
}
}
console.log(newArr);
}
return newArr;
}