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

约瑟夫环问题 Java

2013-12-20 10:51 323 查看
最近研究、整理了一个经典的逻辑问题:与瑟夫环。

定义:约瑟夫环是一个数学的应用问题:已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围。从编号为k的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列。

本例中共给出两种解法计算出圈的人的顺序,第一种使用集合,第二种使用数组。其中第一种是本人自己写出来的,第二种是经典解法。

public class JosephusTest {
public static void main(String[] args) {
int[] orders=getOrderArray(13,0,3);
System.out.println(Arrays.toString(orders));

int[] orders2=getOrderArray2(13,0,3);
System.out.println(Arrays.toString(orders2));

}

private static int[] getOrderArray(int totalCount, int startNum, int selectNum){
//用来存放出圈顺序的数组
int[] orders=new int[totalCount];

List<Integer> list=new ArrayList<Integer>();
for (int i = 0; i < totalCount; i++) {
list.add(i);
}

//第一个出圈的
orders[0]=(startNum+selectNum-1)%totalCount;
//将该位置置为-1,表示已经出圈
list.set(orders[0], -1);
//已经出圈的人数
int num=1;
while(num<totalCount){
//本回合已经报数的人数
int count=0;
//从上一个报数的人的下一个开始
int index=orders[num-1];
while(count<selectNum){
//下标值每次都加1
index=(index+1)%totalCount;
//遇到不为-1的位置,表示这里有人,将count++
if(list.get(index)!=-1){
count++;
}
}

//找到了要出圈的人
orders[num]=list.get(index);
list.set(index, -1);
//已经出圈的人个数+1
num++;
}

for (int i = 0; i < orders.length; i++) {
orders[i]++;
}

return orders;
}

private static int[] getOrderArray2(int totalCount, int startNum, int selectNum){
//用来存放出圈顺序的数组
int[] orders=new int[totalCount];
int orderIndex=0;
//创建有m个值的数组
int[] a=new int[totalCount];
//初始长度,以后出圈一个,长度就减一
int len=totalCount;
//给数组赋值
for(int i=0;i<a.length;i++)
a[i]=i+1;

//index为元素下标,num代表当前要报的数
int index=startNum;
int num=1;
while(len>0){
if(a[index%totalCount]>0){
if(num%selectNum==0){//找到要出圈的人,并把圈中人数减一
orders[orderIndex]=a[index%totalCount];
orderIndex++;
//该位置的人出圈
a[index%totalCount]=-1;
//重新从1开始报数
num=1;
index++;
len--;
}else{
index++;
num++;
}
}else{//遇到空位了,就跳到下一位,但num不加一,也就是这个位置没有报数
index++;
}
}
return orders;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java 数学 约瑟夫环