约瑟夫环问题 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;
}
定义:约瑟夫环是一个数学的应用问题:已知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代码)
- java实现约瑟夫环问题
- 代码详解Java猴子选王问题(约瑟夫环)
- 约瑟夫环的问题与应用(JAVA)
- 使用单链表求解约瑟夫环问题 (利用java中的LinkedList)
- 【Java笔试题】约瑟夫环问题
- Java语言解决约瑟夫环问题(链表实现)
- 约瑟夫环问题-Java数组解决
- 程序员面试金典(动态规划):约瑟夫环问题(java解法)
- java-约瑟夫环问题
- 一个Java面试题(约瑟夫环问题)
- 约瑟夫环问题的Java版解法
- java简单入门程序--约瑟夫环问题
- java用list实现约瑟夫环问题
- java实现简单的约瑟夫环问题(二)
- Java实现约瑟夫环应用问题(精品)
- Java程序练习-约瑟夫环问题
- Java语言解决约瑟夫环问题(ArrayList实现)
- 赌博算法之约瑟夫环问题(JAVA)
- Java实现约瑟夫环问题