前端企业面试题:企业真实案例——28

请实现一个约瑟夫环

首先,你必须先搞清楚什么是约瑟夫环。

相传,在罗马人占领敲他帕特之后,39个犹太人跟约瑟夫以及他的朋友躲到了一个山洞中,39个犹太人决定宁死也不要被敌人抓到,于是决定了一个自杀方式,41个人围成一个圈,由第1个人开始报数,每报数到第3人,该人就必须自杀。然后再由下一个重新报数,直到所有人都自杀身亡为止。然而约瑟夫和他的朋友并不想遵从。他将朋友和自己安排在了第16个和第31个位置,于是逃过了这场死亡游戏。请问他是如何做到的?

它可以衍生为一个通用问题,假设有M个元素

如果把每个人看做一个节点,他们形成了一个单向的循环链表

我们现在假设K=3

当只剩下最后一个元素时

于是我们的核心代码就可以写出来了

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); //最后一个节点

猜你喜欢

转载自blog.csdn.net/GUDUzhongliang/article/details/108513541
今日推荐