图片来源于百度
传说在公元 1 世纪的犹太战争中,犹太历史学家弗拉维奥·约瑟夫斯和他的 40 个同胞被罗马士兵包围。犹太士兵决定宁可自杀也不做俘虏,于是商量出了一个自杀方案。他们围成一个圈,从一个人开始,数到第三个人时将第三个人杀死,然后再数,直到杀光所有人。约瑟夫和另外一个人决定不参加这个疯狂的游戏,他们快速地计算出了两个位置,站在那里得以幸存。请问哪两个位置?写一段程序将 n 个人围成一个圈,并且第 m 个人会被杀掉,计算一圈人中哪两个人会存活。
常规方法 使用数组递归
class JosephusProblem {
constructor(num, rule) {
this.num = num
this.rule = rule
}
startGame() {
const soldiers = this.generateSoldiers()
const survivor = this.startKill()(soldiers, this.rule)
return survivor
}
generateSoldiers() {
const soldiers = []
for (let i = 0; i < this.num; i++) {
const soldiersMess = {
name: `solier-${i+1}`,
isAlive: true,
}
soldiers.push(soldiersMess)
}
return soldiers
}
startKill() {
let count = 0
const kill = (soldiers, rule) => {
for (let i = 0; i < soldiers.length; i++) {
const soldier = soldiers[i]
const { isAlive, name } = soldier
if (isAlive) {
count += 1
if (count === rule) {
soldier.isAlive = false
count = 0
console.log(`${name} has been suicide`)
}
}
const survivor = soldiers.filter(soldier => soldier.isAlive)
if (survivor.length === 2) {
return survivor
}
if (i === soldiers.length - 1) {
i = 0
return kill(soldiers, rule)
}
}
}
return kill
}
}
const p = new JosephusProblem(41, 3)
const survivor = p.startGame()
复制代码
链表方法 关于链表以及链表的实现
class JosephusProblem {
constructor(num, rule) {
this.num = num
this.rule = rule
}
generateSoldiers() {
const link = new LinkedList()
for (let i = 0; i < this.num; i++) {
if (i === 0) {
link.insert(`soldier-${i + 1}`, 'head')
} else {
link.insert(`soldier-${i + 1}`, `soldier-${i}`)
}
}
return link
}
startKill(soldiers) {
while (soldiers.length() !== 2) {
soldiers.movePointer(this.rule)
soldiers.remove(soldiers.pointer.data)
}
return soldiers
}
startGame() {
const soldiers = this.generateSoldiers()
const survivor = this.startKill(soldiers)
return survivor
}
}
const p = new JosephusProblem(41, 3)
const survivor = p.startGame()
复制代码