问题:

丢手帕游戏是约瑟夫问题的一个变种,游戏很简单,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. odoo订餐系统之类型设计

    这次开发的模块是订餐的类型设计,比如大荤 小荤 蔬菜 米饭 等基本数据.1.设计model类,很简单就一个字段: class MyLunchProductionCategory(osv.Model): ...

  2. 微信小程序:java后台获取openId

    一.功能描述 openId是某个微信账户对应某个小程序或者公众号的唯一标识,但openId必须经过后台解密才能获取(之前实现过前台解密,可是由于微信小程序的种种限制,前台解密无法在小程序发布后使用) ...

  3. IIS_部署出错

    在本地开发环境没问题,但是发布到服务器出现:未能写入输出文件“c:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET Fil ...

  4. C. A Mist of Florescence

    链接 [http://codeforces.com/contest/989/problem/C] 题意 给定A B C D四个字符个数,让你构造一个矩阵使得他们的个数恰好那么多,联通块算一块 分析 构 ...

  5. JS 实现计算一段文字中的字节数,字母数,数字数,行数,汉字数。

    看到了匹配,第一个想到了用正则表达式,哈哈,果然很方便.不过正则表达式高深莫测!我还没有研究明白啊..目前学了点皮毛.代码如下: <!DOCTYPE html PUBLIC "-//W ...

  6. linux第一次读书笔记

    第一章 LINUX内核简介 1.1 Unix的历史 1969年的夏天,贝尔实验室的程序员们在一台PDR-7型机上实现了Unix这个全新的操作系统. 1973年,整个Unix系统用C语言进行了重写,给后 ...

  7. linux内核分析第六周学习笔记

    LINUX内核分析第六周学习总结 标签(空格分隔): 20135328陈都 陈都 原创作品转载请注明出处 <Linux内核分析>MOOC课程 http://mooc.study.163.c ...

  8. IT行业的创新的读后感

    一.什么是创新 创新是以新思维.新发明和新描述为特征的一种概念化过程.它原意有三层含义,第一,更新:第二,创造新的东西:第三,改变.创新是人类特有的认识能力和实践能力,是人类主观能动性的高级表现形式, ...

  9. 软件工程项目之摄影App

    摄影app 开发人员:Ives & Dyh 开发功能: 摄影师注册与认证,为年轻摄影师提供成长的空间,发挥一技之长的平台. 用户注册与验证,为有摄影需求的人提供选择摄影师进行个性化拍摄的平台. ...

  10. shell脚本--权限分配

    因为shell脚本内部是很多命令的集合,这些命令也许会涉及到操作某一个文件,而且shell脚本的运行,也是需要当前用户对脚本具有运行的权限,否则,会因为权限不够而失败. 首先最重要的一点:修改权限,只 ...