zoukankan      html  css  js  c++  java
  • 丢手帕问题 (约瑟夫问题)Java实现

    问题:

    丢手帕游戏是约瑟夫问题的一个变种,游戏很简单,N个小孩围成一个圈,标号为1到N,从编号为m的小孩开始报数,报到第L个小孩退出游戏,然后下一个小孩继续从1开始报数,数到第L个小孩退出游戏,如此循环,直到剩下最后一个小孩是胜利者.

    使用环形链表方式解决问题:

    代码如下:

    /**
     * 描述:
     * @作者:niexiaohui
     * @创建时间:2016年12月27日
     * @修改记录:
     */
    public class Test {
        public static void main(String[] args) {
            long starttime=System.currentTimeMillis();
            CircleLinkList game=new CircleLinkList(10000, 99, 533);
            long endtime=System.currentTimeMillis();
            game.play();
            long time2=System.currentTimeMillis();
            System.out.println("创建链表用了"+(endtime-starttime)/1000.0+"秒");
            System.out.println("玩游戏共用了"+(time2-starttime)/1000.0+"秒");
        }
    }
    
    class Child{
        protected int no;
        protected Child nextChild;
        public Child(int no){
            this.no=no;
        }
    }
    
    class CircleLinkList{
        /**
         * 参与游戏人数
         */
        private int playBoys;
        /**
         * 从第几个开始数
         */
        private int startIndex;
        /**
         * 数几个小孩退出
         */
        private int countNum;
        //首个小孩
        private Child firstChild;
        //标识当前小孩
        private Child temp;
        /**
         * 
         * @param playBoys 参与游戏人数
         * @param startIndex 从第几个开始数
         * @param countNum 数几个小孩退出
         */
        public CircleLinkList(int playBoys, int startIndex, int countNum) {
            super();
            this.playBoys = playBoys;
            this.startIndex = startIndex;
            this.countNum = countNum;
            createList();
        }
        /**
         * 创建循环链表
         */
        private void createList() {
            for (int i = 1; i <=playBoys; i++) {
                if (i==1) {//第一个小孩
                    Child child=new Child(i);
                    this.firstChild=child;
                    this.temp=child;
                }else if (i==playBoys) {//最后一个小孩
                    Child child=new Child(i);
                    this.temp.nextChild=child;
                    this.temp=child;
                    this.temp.nextChild=this.firstChild;//最后一个小孩的下一个小孩指向第一个小孩
                }else {
                    Child child=new Child(i);
                    this.temp.nextChild=child;
                    this.temp=child;
                }
            }
        }
        
        /**
         * 玩游戏
         */
        public void play(){
            temp=firstChild;
            //先找到从第几个小孩开始数
            for (int i = 1; i < startIndex; i++) {
                temp=temp.nextChild;
            }
            System.out.println("游戏开始,从第"+temp.no+"个小孩开始数,数到第"+this.countNum+"个小孩退出游戏");
            while (this.playBoys>1) {
                //找到要退出游戏的前一个小孩
                for (int i = 1; i < countNum-1; i++) {
                    temp=temp.nextChild;
                }
                //当前temp是要退出的前一个小孩
                Child leaveChild=temp.nextChild;//要退出的小孩
                System.out.println("当前退出的小孩编号为:" +leaveChild.no);
                temp.nextChild=leaveChild.nextChild;
                if (leaveChild.no==firstChild.no) {//如果要退出的小孩是第一个小孩,则将第一个小孩重置为退出小孩的下一个小孩
                    this.firstChild=leaveChild.nextChild;
                }
                temp=temp.nextChild;
                this.playBoys--;//玩游戏人数少一个
            }
            System.out.println("最后剩下的小孩是:"+ temp.no);
        }
    }

    代码虽然不少,但是并不难懂,有过一点数据结构基础的还是很容易理解的.

    使用数组方式解决问题:

    代码如下:

    /**
     * 描述:
     * 
     * @作者:niexiaohui
     * @创建时间:2017年1月11日
     * @修改记录:
     */
    public class Test4 {
    
        public static void main(String[] args) throws InterruptedException {
            long starttime = System.currentTimeMillis();
            int childrens=10000;//玩游戏的小孩总数
            int countNum=533;//数第几个小孩退出游戏
            int startNum=99;//开始从第几个人开始数
            int count=1;//计数器
            int [] arrays=new int[childrens];
            for (int i = 0; i < arrays.length; i++) {//为数组初始化值
                arrays[i]=1;
            }
            loop:while(true){
                for (int i = 0; i < arrays.length; i++) {
                    if (i<startNum-1) {//第一次循环找到从第几个小孩开始数数
                        continue;
                    }
                    startNum=0;//开始后将startNum清零
                    if (arrays[i]!=0) {//值为0的表示已经退出游戏
                        if (count%countNum==0) {//数到的小孩退出游戏
                            if (childrens==1) {
                                System.out.println("游戏胜利的小孩编号为:"+(i+1));
                                break loop;
                            }
                            arrays[i]=0;//退出游戏的小孩值设为0
                            count=0;//计数器清零,重新计数
                            childrens--;//玩游戏的人数减一
                            System.out.println("编号为"+(i+1)+"的小孩退出游戏");
                        }
                        count++;
                    }
                }
            }
            long time2 = System.currentTimeMillis();
            System.out.println("玩游戏共用了" + (time2 - starttime)/1000.0 + "秒");
        }
    
        
    
    }

    用数组方式解决问题代码少了很多,效率上,我大致比较了下,随着数到第L个小孩退出游戏,即L的增大,链表的速度会提升,相反数组会下降,如果L值很小的话,数组的效率是高于链表的效率的.

  • 相关阅读:
    Entity Framework Core 2.0 新特性
    asp.net core部署时自定义监听端口,提高部署的灵活性
    asp.net core使用jexus部署在linux无法正确 获取远程ip的解决办法
    使用xshell连接服务器,数字键盘无法使用解决办法
    使用Jexus 5.8.2在Centos下部署运行Asp.net core
    【DevOps】DevOps成功的八大炫酷工具
    【Network】Calico, Flannel, Weave and Docker Overlay Network 各种网络模型之间的区别
    【Network】UDP 大包怎么发? MTU怎么设置?
    【Network】高性能 UDP 应该怎么做?
    【Network】golang 容器项目 flannel/UDP相关资料
  • 原文地址:https://www.cnblogs.com/NieXiaoHui/p/6282741.html
Copyright © 2011-2022 走看看