约瑟夫环生者死者游戏(JAVA)

上周日参加一个比赛,在线编程里面有一道就是约瑟夫环的问题,当时脑子转不过来弯集合用的arraylist重复的元素不进行覆盖导致循环一直跳不出来。。。。尼玛当时看了将近2个点好生郁闷。其实这个解决思路很简单,就是构建一个循环链表的数据结构,然后判断要杀死的人中间的间隔,while不断判断就OK了

内容要求:

据说著名犹太历史学家 Josephus有过以下的故事:在罗马人占领乔塔帕特后,39 个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被敌人抓到,于是决定了一个自杀方式,41个人排成一个圆圈,由第1个人开始报数,每报数到第3人该人就必须自杀,然后再由下一个重新报数,直到所有人都自杀身亡为止。然而Josephus 和他的朋友并不想遵从,Josephus要他的朋友先假装遵从,问他俩站在那两个位置才能活着留下。并打印出死亡位置

构建环形链表的数据结构:

package 约瑟夫环;

public class MyLinkedList {
    //内部类 place用于包裹链表的节点信息 包含当前位置信息 前一个节点和后一个节点
    public class Place{
        private String place;
        private Place before;
        private Place after;
        public Place(){

        }

        public Place(String place,Place before,Place after){
            this.place = place;
            this.before = before;
            this.after = after;
        }

        public String getPlace() {
            return place;
        }

        public void setPlace(String place) {
            this.place = place;
        }

        public Place getBefore() {
            return before;
        }

        public void setBefore(Place before) {
            this.before = before;
        }

        public Place getAfter() {
            return after;
        }

        public void setAfter(Place after) {
            this.after = after;
        }
    }
    public Place header = new Place(null,null,null);
    public MyLinkedList(){
        header.setBefore(header);
        header.setAfter(header);
    }
    //添加元素的方法
    public void add(String value){
        Place p = new Place(value,null,null);
        p.setAfter(header);
        p.setBefore(header.getBefore());
        p.getBefore().setAfter(p);
        p.getAfter().setBefore(p);
    }
    //按索引号获得元素
    public Place get(int index){
        Place result = header;
        while(index>0){
            if(result.getAfter()!=header){
                result = result.getAfter();
                index--;
            }else{
                System.out.println("输入索引超过链表长度或当前链表为空");
                System.exit(0);
            }
        }
        return result;
    }
    //判断元素的长度
    public int size(){
        int length =0 ;
        Place result = header;
        while(result.getAfter()!=header){
            result = result.getAfter();
            length++;
        }
        return length;
    }
    //移除当前的节点
    public void remove(Place p){
        Place before = p.getBefore();
        Place after = p.getAfter();
        before.setAfter(after);
        after.setBefore(before);
        p = null;
        System.gc();
    }
}

具体的内容

package 约瑟夫环;

import 约瑟夫环.MyLinkedList.Place;

public class KillGame {
    //引入循环链表
    public MyLinkedList mll = new MyLinkedList();
    //根据人数初始化链表
    public void initList(int number){
        for(int i=0;i"位置"+(i+1));
        }
    }

    public static void main(String[] args){
        KillGame kg = new KillGame();
        //初始化了41个人
        kg.initList(41);
        //计数的标志
        int index = 1;
        //报数位置 初始的时候指向头
        Place p = kg.mll.header;
        //开始杀人游戏
        while(kg.mll.size()>2){
            //假如当前报数位置指向了header节点让其自动移到下一位
            if(p == kg.mll.header){
                p = p.getAfter();
            }
            //假如当前计数为报数的第三个人就杀死他
            if(index%3==0){
                System.out.println(p.getPlace()+"已死亡");
                kg.mll.remove(p);
                p = p.getAfter();
                //否则继续向下进行报数
            }else{
                p = p.getAfter();
            }
            //记数号+1
            index++;
        }
        //当前节点为3个时候跳出循环包含两个幸存者和一个header节点
        System.out.println();
        System.out.println("幸存者所在位置"+kg.mll.get(1).getPlace());
        System.out.println("幸存者所在位置"2Bkg.mll.get(2).getPlace());

    }
}

欢迎讨论

你可能感兴趣的:(算法)