Josephus问题

来源:互联网 发布:淘宝怎样发布二手宝贝? 编辑:程序博客网 时间:2024/06/05 07:36

Josephus问题: N个人编号从1到N ,围坐成一个圆圈。从一号开始传递一个土豆,经过M次传递后拿着土豆的人被清除离座,围坐的圆缩紧,由坐在被清除的人的后面的人拿起土豆继续进行游戏,最后剩下的人获胜。如:M=1 N=5 被清除的人的顺序为2,4,1,5。


方法一:按照题目提示,问题处理关键为循环数组,关键在处理下标。

源代码如下:

public class PT36 {
public static void main(String args[]){
/*
* 初始化各类参量
*/
int n = 5, m =1, from = 0;
List<Integer> list = new ArrayList<Integer>();
for(int i= 0 ; i < n ; i++){
list.add(i+1);
}
System.out.print(list);
/*
* 游戏开始
*/
while(list.size() != 1){
if((from+m) <list.size())  /*  判断标识和移动之后的标识是否越界*/
from = from+m;
else{
int temp = list.size() - from;
from =m-temp;
if(from >= list.size()){
do{
from = from-list.size();
}while(from >= list.size());
} /*  下标越界操作,在数组越来越小时要使用循环才可以保证下标移入到数组内部 */

}
System.out.print(list.get(from));
list.remove(from);
if(from == list.size())
from = 0; /*打印被弹出的数组,同时做判断是有在删除数字之后,下标越界*/
}
System.out.print(list);
}
}

上述方法的while可以用递归来表示,但会额外增加存储空间,不建议使用。


方法二:将一个循环数组改变为不断加长的数组,例如[1,2,3,4,5] -> [1,3,4,5]->[1,3,5]->[1,3,5,1,3,5]->[3,5,3,5]->[3,3]->3

源代码如下:

public class PT36_2 {
public static void main(String args[]){
/*
* 完成初始化。
*/
int m = 3 , n =5 , index = 0 , pianyi = 0;
List<Integer> list = new ArrayList<Integer>();
for(int i=0;i<n;i++){
list.add(i+1);
}
System.out.print(list);
/*
* 定义空数组,用于数组增加
*/
List<Integer> templist = new ArrayList<Integer>();
templist.addAll(list);
/*
* 游戏开始
*/
while(!issimple(list)){
if(index + m < list.size()){
/*
* 确定标识位置,同时在删除之后根据拼接的次数完成标志偏移量的修改。
*/
index = index+m;
list=myremove(list, list.get(index));
if(index >= list.size()/(pianyi+1))
index= index - pianyi;
templist.clear();
templist.addAll(list);
System.out.print(list);
}else{
do{
/*
* 拼接数组,同时记录拼接次数
*/
list.addAll(templist);
pianyi ++;
}while(index + m >= list.size());

}
}
/*
* 显示最终获胜者
*/
System.out.println(list.get(0));


}
/*
* 由于数组拼接,可能导致同意元素多个,所以List提供的remove方法无法满足条件,自己写方法用于删除所有同类元素
*/
private static List<Integer> myremove(List<Integer> list , int x) {
List<Integer> templist1 = list;
for(int i=0; i<list.size();i++){
if(list.get(i) == x){
list.remove(i);
}
}
templist1 = list;
return templist1;
}
/*
* 判断目前的ArrayList是否只包含最后胜出的元素
*/
private static boolean issimple(List<Integer> list){
boolean issimple = true;
int example = list.get(0);
for(int i = 0 ; i<list.size();i++){
if(example != list.get(i)){
issimple = false;
break;
}
}
return issimple;
}
}

游戏分析与实现完成!

0 0