问题:

丢手帕游戏是约瑟夫问题的一个变种,游戏很简单,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. Luogu P1514 引水入城

    我承认我有点懒(洛谷已经发过题解了,但我发誓要坚持写博客) 这道题坑了我3天…… 首先一看就与染色问题类似,果断BFS(写DFS炸了) 先将最上面(靠近水)的一行全部扔进队列里,做一遍BFS 再对最下 ...

  2. 系统引导修复,grub2下的各种骚作

    新买的xps装了一个rhel7.5,各种恶心... 第一次:升级内核之后居然引导不了! 进入bios setup,把bios 引导的文件选择为 grub64.eif,成功进入系统 第二次:升级grub ...

  3. python中和生成器协程相关yield from之最详最强解释,一看就懂(二)

    一. 从列表中yield  语法形式:yield from <可迭代的对象实例> python中的列表是可迭代的, 如果想构造一个生成器逐一产生list中元素,按之前的yield语法,是在 ...

  4. python中和生成器协程相关的yield之最详最强解释,一看就懂(一)

    yield是python中一个非常重要的关键词,所有迭代器都是yield实现的,学习python,如果不把这个yield的意思和用法彻底搞清楚,学习python的生成器,协程和异步io的时候,就会彻底 ...

  5. 基于BlogEngine.NET搭建个人博客

    早些时候在万网以我自己的英文名买了个域名 giantliu.com又看到万网有一个免费版本的虚拟主机,而且还支持.net4.5这年头支持.net4.5的免费主机不多,本来想用阿里云/windows a ...

  6. 跨平台、跨语言应用开发,Elements 介绍

    目录 1,Elements 介绍 2,Elements 版本 3,Elements 能干嘛 4,Elements  IDES 5,Elements 工具 1,Elements 介绍 RemObject ...

  7. 一个高性能的对象属性复制类,支持不同类型对象间复制,支持Nullable<T>类型属性

    由于在实际应用中,需要对大量的对象属性进行复制,原来的方法是通过反射实现,在量大了以后,反射的性能问题就凸显出来了,必须用Emit来实现. 搜了一圈代码,没发现适合的,要么只能在相同类型对象间复制,要 ...

  8. 《Linux内核分析》第七周学习笔记

    <Linux内核分析>第七周学习笔记 可执行程序的装载 郭垚 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/co ...

  9. 20135327郭皓--Linux内核分析第八周 进程的切换和系统的一般执行过程

    第八周 进程的切换和系统的一般执行过程 一.进程切换的关键代码switch_to分析 1.进程调度与进程调度的时机分析 不同类型的进程有不同的调度需求 第一种分类: I/O-bound:频繁进行I/O ...

  10. 第一次Spring总结

    第一阶段:下载了类似app使用,并做了对比,分析,对自己的app有了一些构思,完成了环境的配置.在这一阶段,一开始只有两个女生显得有点弱,面对从未接触过的app项目,首先就是配置环境方面的,在经过班上 ...