问题:

丢手帕游戏是约瑟夫问题的一个变种,游戏很简单,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. NOIP2018题解

    Preface 联赛结束后趁着自己还没有一下子把题目忘光,所以趁机改一下题目. 没有和游记一起写主要是怕篇幅太长不美观. 因此这里我们直接讲题目,关于NOIP2018的一些心得和有趣的事详见:NOIP ...

  2. flask-admin 快速打造博客 系列一

    前言: 我想分享flask+flask-admin快速打造博客的详细教程,可是发现网易课堂已经有相应的免费课堂了,所以就不打算一点一滴的在这里做笔记,分享这些东西了.所以我主要集中在flask-adm ...

  3. flask_admin 笔记七 扩展功能

    高级功能 1,开启CSRF保护 要将CSRF保护添加到由ModelView实例生成的表单中,请通过指定form_base_class参数在ModelView子类中使用SecureForm类: from ...

  4. 基于RC4加密算法的图像加密

    基于RC4加密算法的图像加密 某课程的一个大作业内容,对图像加密.项目地址:https://gitee.com/jerry323/RC4_picture 这里使用的是RC4(流.对称)加密算法,算法流 ...

  5. 《Linux及安全》课程实践二

    编译生成新内核 一.实践原理 Linux模块是一些可以作为独立程序来编译的函数和数据类型的集合.之所以提供模块机制,是因为Linux本身是一个单内核.单内核由于所有内容都集成在一起,效率很高,但可扩展 ...

  6. ubuntu——caffe配置deeplab

    1. 下载deeplab 2. 安装matio sudo apt-get install libmatio-dev 3. 修改Makefile文件 LIBRARIES += glog gflags p ...

  7. 20150401 作业2 结对 四则运算ver 1.0

    Web項目下 Tomcat服務器的路徑 /WebContant/ 目錄下 SE2_2.jsp <%@ page language="java" contentType=&qu ...

  8. synchronized关键字的学习与总结

  9. tensorflow win10 系统下安装

    安装tensorflow gpu版本 Step1 安装CUDA8.0 进入这个云盘地址下载,密码5aoc 进行CUDA8.0下载.下载完成后解压,打开exe文件直接按照默认进行安装,安装步骤比较繁琐, ...

  10. Linux curl 一例

    root@PC-RENGUOQIANG:~# curl http://kermit:kermit@192.168.66.182:8080/activiti-rest/service/repositor ...