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值很小的话,数组的效率是高于链表的效率的.

  • 相关阅读:
    其实那女子根本就不是在三楼死的
    ARX工程必须使用release模式编译
    解决64bit不能连接access的问题
    bootstrap例子
    bootstrap登录界面
    Bootstrap3.0入门学习系列教程
    CentOS(Linux)中解决MySQL乱码
    linux yum命令详解
    CentOS yum 安装 Apache + PHP + MySQL
    Centos下配置php环境
  • 原文地址:https://www.cnblogs.com/NieXiaoHui/p/6282741.html
Copyright © 2011-2022 走看看