Javascript中的循环链接列表同胞游戏

Javascript中的循环链接列表同胞游戏,javascript,linked-list,circular-list,Javascript,Linked List,Circular List,我在O'Reilly的Javascript数据结构和算法中发现了这个问题“根据传说,一世纪的犹太历史学家弗拉维乌斯·约瑟夫大约 在战争期间与40名同胞一起被罗马士兵俘虏 犹太-罗马战争。犹太士兵决定他们宁愿自杀也不愿被杀害 俘虏并设计了他们的死亡计划。他们要围成一个圈并杀戮 每三名士兵中就有一名,直到他们全部死去。约瑟夫斯和另外一名决定 不想参与其中,并迅速计算出他们需要将自己放在哪里 所以他们将是最后的幸存者。写一个程序,允许你放置n 将所有人围成一个圈,并指定每一个mth人都将被杀害 应确定

我在O'Reilly的Javascript数据结构和算法中发现了这个问题“根据传说,一世纪的犹太历史学家弗拉维乌斯·约瑟夫大约 在战争期间与40名同胞一起被罗马士兵俘虏 犹太-罗马战争。犹太士兵决定他们宁愿自杀也不愿被杀害 俘虏并设计了他们的死亡计划。他们要围成一个圈并杀戮 每三名士兵中就有一名,直到他们全部死去。约瑟夫斯和另外一名决定 不想参与其中,并迅速计算出他们需要将自己放在哪里 所以他们将是最后的幸存者。写一个程序,允许你放置n 将所有人围成一个圈,并指定每一个mth人都将被杀害 应确定圆圈中最后两个人的人数。循环使用 链表来解决这个问题。”

这是我的解决方案

function Node(element) {
    this.element = element;
    this.next = null;
}

function LList() {
    this.head = new Node("head");
    this.head.next = this.head;
    this.find = find;
    this.insert = insert;
    this.display = display;
    this.findPrevious = findPrevious;
    this.remove = remove;
    this.advance = advance;
    this.count = count;
}

function remove(item) {
    var prevNode = this.findPrevious(item);
    if (!(prevNode.next == this.head)) {
        prevNode.next = prevNode.next.next;
    }
}
function findPrevious(item) {
    var currNode = this.head;
    while (!(currNode.next == this.head) &&
        (currNode.next.element != item)) {
        currNode = currNode.next;
    }
    return currNode;
}
function display() {
    var currNode = this.head;
    while (!(currNode.next == this.head)) {
        print(currNode.next.element);
        currNode = currNode.next;
    }
}
function count() {
    var currNode = this.head;
    var count = 0;
    while (!(currNode.next == this.head)) {
        count++
        currNode = currNode.next;
    }
    return count;
}
function find(item) {
    var currNode = this.head;
    while (currNode.element != item) {
        currNode = currNode.next;
    }
    return currNode;
}
function insert(newElement, item) {
    var newNode = new Node(newElement);
    var current = this.find(item);
    newNode.next = current.next;
    current.next = newNode;
}

function advance(item, n) {
    var currNode = this.find(item);
    for (let i = n; i > 0; i--) {
        currNode = currNode.next;
    }
    return currNode;
}



function survivor(number, position) {
    //40 compatriots
    //kill every third soldier. advance by 3
    //last two survivors

    //place n people in a circle
    var compatroits = new LList();
    var currNode = compatroits.head;

    for (let i = 1; i <= number; i++) {
        compatroits.insert(i, currNode.element);
        currNode = currNode.next;
    }

    //kill every mth person in the circle
    //start from head
    var currItem = compatroits.head.element;
    while (compatroits.count() > 2) {
        //advance mth person
        var killNode = compatroits.advance(currItem, position);

        //set new start point to m.next node
        currItem = killNode.next.element;

        //remove mth person
        compatroits.remove(killNode.element);
    }


    //determine the last two people in the circle
    return compatroits.display();
}
功能节点(元素){
this.element=元素;
this.next=null;
}
函数{
this.head=新节点(“head”);
this.head.next=this.head;
this.find=find;
this.insert=插入;
this.display=显示;
this.findPrevious=findPrevious;
这个。移除=移除;
这个。前进=前进;
this.count=计数;
}
功能移除(项目){
var prevNode=this.findPrevious(项目);
if(!(prevNode.next==this.head)){
prevNode.next=prevNode.next.next;
}
}
功能findPrevious(项目){
var currNode=this.head;
while(!(currNode.next==this.head)&&
(currNode.next.element!=项目)){
currNode=currNode.next;
}
返回节点;
}
函数显示(){
var currNode=this.head;
而(!(currNode.next==this.head)){
打印(currNode.next.element);
currNode=currNode.next;
}
}
函数计数(){
var currNode=this.head;
var计数=0;
而(!(currNode.next==this.head)){
计数++
currNode=currNode.next;
}
返回计数;
}
函数查找(项){
var currNode=this.head;
while(currNode.element!=项目){
currNode=currNode.next;
}
返回节点;
}
函数插入(新元素,项){
var newNode=新节点(newElement);
var current=此项。查找(项目);
newNode.next=current.next;
current.next=newNode;
}
功能推进(项目,n){
var currNode=this.find(项目);
对于(设i=n;i>0;i--){
currNode=currNode.next;
}
返回节点;
}
功能幸存者(数量、位置){
//40名同胞
//每杀三名士兵,前进三步
//最后两名幸存者
//把n个人围成一个圈
var compatroits=new LList();
var currNode=compatroits.head;
for(设i=1;i=2){
//高级mth人员
var killNode=compatroits.advance(当前项目、位置);
//将新起点设置为m.next节点
currItem=killNode.next.element;
//移除第m个人
compatroits.remove(killNode.element);
}
//确定圈中的最后两个人
返回compatroits.display();
}

有谁能找到更有效的方法来解决这个问题吗?

当然有更有效的方法——特别是如果你愿意制作双链接列表的话。这对我来说可能是个好问题。但实际上,实际产出存在一些问题。例如,当我运行
survivor(40,3)
时,它看起来像是一个41-40加上头部的列表。然后每四个人删除一次。谢谢马克的反馈。我认为它似乎删除了第四个人,因为每当删除一个节点时,它就会重新开始计数。因此,已删除的节点不算作一个,而是将删除节点后的下一个节点算作一个。是的,它确实创造了40个元素加上头部。我确实认为我可以做出调整,以消除这两个bug。我也会在codereview上讨论它。再次感谢您的反馈