您的位置:首页 > 编程语言 > Java开发

java实现约瑟夫环

2010-09-03 15:15 357 查看
题目:由n个人围成一个首尾相连的圈报数。
*从第一个人开始,从1开始报数,报到k的人出圈,
*剩下的人继续从1开始报数,直到所有的人都出圈为止。
*对于给定的k和n,求出所有人的出圈顺序.

import java.util.ArrayList;
import java.util.List;

public class Monkey {
private final static String SVN_VERSION = "$Id$";
public List sourceList= new ArrayList();//按顺序递增的序列链表,作为源链表,从该链表中移除报了数的成员
public List finalList= new ArrayList();//最终的结果链表;初始化时链表里全部成员都为零,长度跟源链表一样,每次从源链表中移除一个报数成员,就在该链表中的相同位置增加被移除的序号
public int k;
public int n;

/**
* 初始化源链表和最终的结果链表,原链表中的存放的是整数,按顺序递增;结果链表中存放的全部是零
* @param k 每报k次数后重新报数
* @param n 一共有n个人围成一圈报数
*/
public void init(int k,int n){
this.k=k;
this.n=n;
for(int i=1;i<=n;i++){
sourceList.add(i);
finalList.add(0);
}

}
/**
* 排序过程
*/
public void sequence(){
int index =0;//原链表的index,相当于报数指针
int seqNum =1;//报数报到K的人,出列顺序
System.out.println("链表总长 n="+n+";每次选择k个人报数,K="+k);
//只要还有人没报数报到k,就继续循环下去
while(!sourceList.isEmpty()){
System.out.println("每移除一次报数后的链表内容:");
//每次移除一个报到k的人时,从1开始报数,打印这时源链表中的内容
for(int a=0;a<sourceList.size();a++){
System.out.println("sourceList["+a+"]="+sourceList.get(a));
}
//count相当于报数K的计数器,大于k从1开始报数,报到k时移除k,并且跳出该循环
for(int count=1;count<=k;count++){
System.out.println("sourceList.size()="+sourceList.size()+";count="+count+";index="+index+";seqNum="+seqNum);
//当总人数只剩下一个人的时候
if(sourceList.size() == 1){
int objInt = (Integer) sourceList.get(0);
System.out.println("END--报数第K个... sourceList[0]="+objInt);
sourceList.remove(0);
finalList.set(objInt-1, seqNum);
break;
}
//当index已经循环到链表最后元素,并且最后一个元素被移除了,index从零算起
if(index == sourceList.size()){
index =0;
}else if(index > sourceList.size())//当index已经循环到链表最后元素可能超过了链表的总长度,index从它多余的元素开始从头算起
{
index =index%(sourceList.size());
}
System.out.println("【index】 =="+index);
//报数还没报到k时,Index增加一,表示报数向下一个元素移动
if(count !=k){
index++;
}else{//报数报到k时,原链表移除该元素,结果链表相应的位置增加被移除的顺序号,并且跳出该循环,从下一个位置开始重新报数
int objInt = (Integer) sourceList.get(index);
System.out.println("@@@报数第K个... sourceList["+index+"]="+objInt);
sourceList.remove(index);
finalList.set(objInt-1, seqNum);
seqNum++;
break;
}
}
}
System.out.println("排序后的链表内容为:");
//打印结果链表
for(int a=0;a<finalList.size();a++){
System.out.println("finalList["+a+"]="+finalList.get(a));
}
}
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Monkey obj = new Monkey();
obj.init(3, 6);
obj.sequence();
}
}


这段代码是自己写的,辛苦调试了半天,基本思路比较简单,就是做两个List,第一个是用循环遍历源List模拟围成圈子报数的人,每到第k个人就把源List里的这个位置的对象remove掉,并且在结果List中同样的位置加入第几次被移除这个次数,位置是源List里保存的对象。

这里比较难调试的地方是,当源List的长度小于k时,移除源List里的对象后计算下一个index的位置比较麻烦,需要注意循环中优先判断源List的长度只剩一个人的情况,再判断k等于list长度,这是把index置0相当于把指针移到list第一个元素,然后判断k超过list长度,取(k%list的长度)这个余数作为index新坐标,最后再判断当前这个循环式第几个人在报数,不是k就index递增,是k的话就移除当前元素。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: