问题:

丢手帕游戏是约瑟夫问题的一个变种,游戏很简单,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值很小的话,数组的效率是高于链表的效率的.

丢手帕问题 (约瑟夫问题)Java实现的更多相关文章

  1. 丢手帕问题(环形链表)---Java 待优化

    /** * * @author Administrator * 功能:丢手帕问题 */ package com.litao; public class Demo4 { /** * @param arg ...

  2. java丢手帕 约瑟夫问题

    一.问题描述:     n个人围成一个圈,编号为1~n,从第一号开始报数,报到3的倍数的人离开,一直数下去,直到最后只有一个人,求此人编号. 二.问题提示:  使用一维数组,数组元素初始为1,从1开始 ...

  3. 丢手帕问题即约瑟夫问题的PHP解法

    问题描述:n个人排成一圈.从某个人开始,依次报数,数到m的人被杀死.下一个人重新从1开始报数,数到m的人被杀死.直到剩下最后一个人. 解决思路:从数学角度去看,每一次报数决定谁去死是一个n.m的求余数 ...

  4. java面向对象编程--Josephu问题(丢手帕问题)

    Josephu问题为:设编号为1,2,...n的n个人围坐一圈,约定编号为k(1<=k<=n)的人从1开始报数,数到m的那个人出列,它的下一位又从1开始报数,数到m的那个人又出列,依次类推 ...

  5. 约瑟夫环形链表问题、丢手帕问题、剑指offer圆圈中最后一个数问题

    public class Solution { // 左神解法,本题本质还是报数为m-1的倍数的人死.求最后一个活着的人是初始时候的哪个人       /* 报数(A) 实际人员编号(B)      ...

  6. j使用数组实现约瑟夫环 java

    我们首先来看一下约瑟夫环问题: 给定m个人,m个人围成一圈,在给定一个数n,从m个人中的第一个人每第n个人便将其除去,求被最后一个出去的人的编号. 思路: 建立一个长度为m+1的数组,将其的内容初始化 ...

  7. 约瑟夫环 java实现

    问题: N个人从1到N编号.围城一圈,从1開始报数, 数到X时,将X的编号输出,并将那个人踢出, 下一个从1再開始报数,直到全部人都出去 思路: 就是计数.移除,没有太深的思想,直接上代码: pack ...

  8. P1996_约瑟夫问题(JAVA语言)_可能是最简单的解法了!

    思路:使用队列模拟. 判断是否为出圈的数.如果不是,把数加入队列尾部:如果是,输出并删除. 题目背景 约瑟夫是一个无聊的人!!! 题目描述 n个人(n<=100)围成一圈,从第一个人开始报数,数 ...

  9. 约瑟夫问题 java

    约瑟夫环:已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围.从编号为k的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,直到圆桌周围 ...

随机推荐

  1. BZOJ 4804: 欧拉心算

    数论题不多BB,直接开始推导吧: \(\sum_{i=1}^n \sum_{j=1}^n \phi(gcd(i,j))\) \(=\sum_{i=1}^n \sum_{j=1}^n \sum_{d=1 ...

  2. [Partition][Index]对于Partition表而言,是否Global Index 和 Local Index 可以针对同一个字段建立?

    对于Partition表而言,是否Global Index 和 Local Index 可以针对同一个字段建立? 实验证明,对单独的列而言,要么建立 Global Index, 要么建立 Local ...

  3. ngx_lua 模块

    ngx_lua模块的原理: 1.每个worker(工作进程)创建一个Lua VM,worker内所有协程共享VM:2.将Nginx I/O原语封装后注入 Lua VM,允许Lua代码直接访问:3.每个 ...

  4. 深入理解USB流量数据包的抓取与分析

    0x01 问题提出 在一次演练中,我们通过wireshark抓取了一个如下的数据包,我们如何对其进行分析? 0x02 问题分析 流量包是如何捕获的? 首先我们从上面的数据包分析可以知道,这是个USB的 ...

  5. 如何在命令长度受限的情况下成功get到webshell(函数参数受限突破、mysql的骚操作)

    0x01 问题提出 还记得上篇文章记一次拿webshell踩过的坑(如何用PHP编写一个不包含数字和字母的后门),我们讲到了一些PHP的一些如何巧妙地绕过数字和字母受限的技巧,今天我要给大家分享的是如 ...

  6. 类似于PLC上升沿的TRIO代码示例

    需求:    一个自复位按钮,控制灯泡的亮与灭(按钮按一次灯亮,再按一次灯灭依次循环). 简短的代码,若大家有更好的思路可以评论区留言. DIM in_button,op_lamp,var_middl ...

  7. mac下查看和设置环境变量

    1.查看环境变量 命令    env 2.修改环境变量 命令    cd ~ && ls -a && sudo vim .bashrc 编辑输入要添加的环境变量 3.s ...

  8. 关于Runtime error

    别人说的,但我感觉是因为你的操作是不符合语言规定的,让编译器无法识别,运行不出

  9. visual studio2013安装及测试

    visual studio2013自同学处拷贝安装至本机,由于安装包较大采用了双重压缩,解压时费了点时间,安装过程更是用了一个小时之久. 1.安装环境: 本机配置:Windows8,Intel(R)C ...

  10. PHP开发:Eclipse版环境配置

    软件: 1.eclipse php版本下载地址:http://www.eclipse.org/downloads/packages/eclipse-php-developers/heliosr 2.A ...