请实现一个约瑟夫环
首先,你必须先搞清楚什么是约瑟夫环。
相传,在罗马人占领敲他帕特之后,39个犹太人跟约瑟夫以及他的朋友躲到了一个山洞中,39个犹太人决定宁死也不要被敌人抓到,于是决定了一个自杀方式,41个人围成一个圈,由第1个人开始报数,每报数到第3人,该人就必须自杀。然后再由下一个重新报数,直到所有人都自杀身亡为止。然而约瑟夫和他的朋友并不想遵从。他将朋友和自己安排在了第16个和第31个位置,于是逃过了这场死亡游戏。请问他是如何做到的?
它可以衍生为一个通用问题,假设有M个元素
如果把每个人看做一个节点,他们形成了一个单向的循环链表
我们现在假设K=3
当只剩下最后一个元素时
扫描二维码关注公众号,回复:
11648228 查看本文章
于是我们的核心代码就可以写出来了
while(node.next != node){
1 将指针移动K-1步
2 重新建立连接删除当前节点
3 修正指针位置到下一个
}
我们先准备节点类
function Node(name){
this.name = name;
this.next;
}
创建一个长度为10的单向循环链表
let head = temp = new Node(1);
for(let i=2; i<=10; i++){
temp.next = new Node(i);
temp = temp.next;
}
temp.next = head;
创建出我们的指针类
function Pointer(node){
this.current = node;
this.move = function(){
this.prev = this.current; //记录前一格
this.current = this.current.next; //当前节点向前移动一格
}
}
接下来是完整代码
function Node(name){
this.name = name;
this.next;
}
function Pointer(node){
this.current = node;
this.move = function(){
this.prev = this.current; //记录前一格
this.current = this.current.next; //当前节点向前移动一格
}
}
//准备好链表内容
let head = temp = new Node(1);
for(let i=2; i<=10; i++){
temp.next = new Node(i);
temp = temp.next;
}
temp.next = head;
//创建指针,从head开始
var p = new Pointer(head);
//设定间隔为3
let step = 3;
//只要next没有指向元素自身,则循环继续
while(p.current != p.current.next){
//指针移动step-1步
for(let i=0; i<step-1; i++){
p.move();
}
//重新建立连接并删除当前元素
p.prev.next = p.current.next;
//修正指针位置到下一个(跟指针move是有区别的)
p.current = p.current.next;
}
console.log(p.current); //最后一个节点