最近研究、整理了一个经典的逻辑问题:与瑟夫环。
定义:约瑟夫环是一个数学的应用问题:已知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){//下标值每次都加1index=(index+1)%totalCount;//遇到不为-1的位置,表示这里有人,将count++if(list.get(index)!=-1){count++;}}//找到了要出圈的人orders[num]=list.get(index);list.set(index, -1);//已经出圈的人个数+1num++;}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;}
明天的希望,让我们忘了今天的痛苦