丢手帕问题 (约瑟夫问题)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值很小的话,数组的效率是高于链表的效率的.

以上是 丢手帕问题 (约瑟夫问题)Java实现 的全部内容, 来源链接: utcz.com/z/391529.html

回到顶部