约瑟夫环问题:
古代某法官要判决N个犯人的死刑,他有一条荒唐的法律,让犯人站成一个圆圈,从第S个人开始数起,每数到第D个犯人,就拉出来处决,然后再数D个,数到的人再处决……直到剩下的最后一个可赦免。使用数组存储每个人的编号,数组下标按环形方式递增。对于N、S、D的任意一组值,显示出环者次序,求出正确的解。
方法一:
可以用数组来存放N个数,相当于N个数排成的圈;用整型变量指向当前数到的数组元素, 相当于人的手指;划掉一个数的操作,就用将一个数组元素置0的方法来实现。人工数的时候,要跳过已 经被划掉的数,那么程序执行的时候,就要跳过为0的数组元素。注意,当指向当前数到的数组元素的整 型变量指向数组中最后一个元素(下标为N-1)时,再数下一个,则该整型变量要指回到数组的第一个元 素(下标为0),这样才像一个圈。
方法二:采用单向循环链表完成此题。Java API提供了丰富的集合类型,封装了各种数据结构(链表、散列、树、图等),链表的建立和相关操作可使用java.util包中提供的相关集合类。
import java.util.Scanner; /** *使用数组实现约瑟夫环问题 *由m个人围成一个首尾相连的圈报数。 *从第一个人开始,从1开始报数,报到n的人出圈, *剩下的人继续从1开始报数,直到所有的人都出圈为止。 *对于给定的m和n,求出所有人的出圈顺序. */
第一种:
public class Ring{ public static void main(String args[]){ int m=3,n=5,c=0,ln=n ,i=0; int[] j=new int[20]; for(i=0;i<n;i++) j[i]=i+1; i=0; while(ln>1){ if(j[i]!=0){ c++; if(c==m){ c=0; j[i]=0; ln--; } } i++; if(i==n) i=0; } for(i=0;i<n&&j[i]==0;i++); System.out.println(j[i]); } }
第二种 public class RingTest{ public static void main(String[] args){ System.out.println("程序说明如下:"); System.out.println("由m个人围成一个首尾相连的圈报数。从第一个人开始,从1开始报数,报到n的人出圈,剩下的人继续从1开始报数,直到所有的人都出圈为止。对于给定的m和n,求出所有人的出圈顺序."); //提示输入总人数 System.out.println("请输入做这个游戏的总人数:"); Scanner sca=new Scanner(System.in); int m=sca.nextInt(); //提示输入要出圈的数值 System.out.println("请输入要出圈的数值:"); int n=sca.nextInt(); System.out.println("按出圈的次序输出序号:"); //创建有m个值的数组 int[] a=new int[m]; //初始长度,以后出圈一个,长度就减一 int len=m; //给数组赋值 for(int i=0;i<a.length;i++) a[i]=i+1; //i为元素下表,j代表当前要报的数 int i=0; int j=1; while(len>0){ if(a[i%m]>0){ if(j%n==0){//找到要出圈的人,并把圈中人数减一 System.out.print(a[i%m]+" "); a[i%m]=-1; j=1; i++; len--; }else{ i++; j++; } }else{//遇到空位了,就跳到下一位,但j不加一,也就是这个位置没有报数 i++; } } } }
作者:http://www.loverseo.com