1.什么是Josephus问题
什么?!你还不知道什么是Josephus问题?太out了吧。
就是有n个人未作在一个圆桌周围,现从第s个人开始报数,数到第m的人出列,然后从出列的下一个人重新开始报数,数到第m的人又出列,如此反复,直到所有的人全部出列为止。Josephus问题是:对于任意给定的n、s、m,求出按出列次序得到的n个人员的序列。
在这里,我们先来做一个简单的例子,在这个简单的例子的基础上,再去解决Josephus问题,那么会简单好多,有兴趣可以借鉴我的方法去实现,我这里主要是向大家展示数组模拟的链表。
我们做的简单的例子是求的什么呢?就是剩下的最后一个人的索引,而且s为1.
2.解决思路
利用上篇我说道的数组模拟链表,首先先建一个长度为n的数组。当数到m-1时,修改第m-1的值为第m+1,这样指向m的索引就没有了,m也就被“删除”了。
如此循环,当循环到某索引出的值,等于此处的索引时,那么也就是这个数组剩下“最后一个”元素。由于数组模拟的链表不是真正的删除,这点我们在这线不讨论了。
3.说的好不如代码敲得好,代码能够说明一切
/*
*作者:曹建新
*实现功能:利用数组模拟链表解决。。问题
*参数:第一个参数为n,第二个参数m*/
class ArrayList{
public static void main(String[] args) {
//判断用户是否给出参数
//如果没有给出2个,则提示然后退出,否则继续
if(args.length!=2){
System.out.println("You must give two argument!");
System.exit(0);
}
//System.out.println(("123").matches("[0-9]*"));
//判断给的两个参数是否都是可以转换为数字
//如果两个参数中有一个不是,则提示,然后退出,否则继续
for(int i=0; i<args.length; i++){
if( !args[i].matches("[0-9]*")) {
System.out.println("Two argument must be Number!");
System.exit(0);
}
}
//利用给出的参数进行数组的初始化
int[] a=new int[Integer.parseInt(args[0])];
for (int i=0; i<a.length-1; i++){
a[i]=i+1;
}
a[a.length-1]=0;
int index=0; //用来存储当前位置
int countNum=0; //用来计数
//测试数组是否赋值成功
/*for(int i=0; i<a.length; i++){
System.out.println(a[index]);
index=a[index];
}*/
//当某索引中的值与索引相同时,说明只剩下一个了
while(a[index] !=index ){
countNum ++;
//判断是否应该有人退出
//要改数到的那个同学的上一位,所以需要-1
//删除,就是把前一个索引处的值改成当前索引所对应的值
if (countNum==Integer.parseInt(args[1])-1){
a[index]=a[a[index]];
countNum=0;
}
index=a[index]; //设置下一个索引为当前索引对一个的值
}
System.out.println(index);
}
}
写个博客,换了好几台电脑,现在用的不是我电脑,没有java运行环境,就不给大家贴调用的结果了,给大家写一下调用的方法吧。java ArrayList 10 3,结果为3。
代码中的注释写的很详细,哪有错误和不明白的地方都可以说出来,大家一起进步。另外,这个思路是面向过程的思路写的,也欢迎大家用面向对象的思路写一下,然后给我发一个链接,我回很认真的拜读。