约瑟夫环是一个数学的应用问题:已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围。从编号为k的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列。
1 package MyTest; 2 3 /** 4 * 约瑟夫环的问题 5 * @author Administrator 6 * 7 */ 8 import java.util.*; 9 public class JosephCircle { 10 11 public static void main(String[] args) { 12 Scanner in = new Scanner(System.in); 13 while(in.hasNext()){ 14 int peopleNum = in.nextInt(); 15 int k = in.nextInt(); 16 joseph(peopleNum, k); 17 } 18 in.close(); 19 20 } 21 22 private static void joseph(int peopleNum, int k) { 23 //初始化人的ID 24 List<Integer> circle = new LinkedList<>(); 25 for(int i =1; i <= peopleNum; i++){ 26 circle.add(i); 27 } 28 29 //从第flag个开始计数 30 int flag = 0; 31 while(circle.size() > 0){ 32 flag = flag + k; 33 34 //第k个人的索引位置 35 flag = flag % (circle.size()) - 1; //这个可以实现循环!!!! 36 37 //判断是否到队尾,处理特殊情况,把flag置0 38 if(flag < 0){ 39 System.out.println(circle.get(circle.size()-1)); 40 circle.remove(circle.size() -1); 41 flag = 0; 42 } 43 else{ 44 System.out.println(circle.get(flag)); 45 circle.remove(flag); 46 } 47 } 48 } 49 50 }
约瑟夫环变种:
输入一个由随机数组成的数列(数列中每个数均是大于0的整数,长度已知),和初始计数值m。从数列首位置开始计数,计数到m后,将数列该位置数值替换计数值m,并将数列该位置数值出列,然后从下一位置从新开始计数,直到数列所有数值出列为止。如果计数到达数列尾段,则返回数列首位置继续计数。请编程实现上述计数过程,同时输出数值出列的顺序
比如: 输入的随机数列为:3,1,2,4,初始计数值m=7,从数列首位置开始计数(数值3所在位置)
第一轮计数出列数字为2,计数值更新m=2,出列后数列为3,1,4,从数值4所在位置从新开始计数
第二轮计数出列数字为3,计数值更新m=3,出列后数列为1,4,从数值1所在位置开始计数
第三轮计数出列数字为1,计数值更新m=1,出列后数列为4,从数值4所在位置开始计数
最后一轮计数出列数字为4,计数过程完成。
输出数值出列顺序为:2,3,1,4。
• 要求实现函数:
void array_iterate(int len, int input_array[], int m, int output_array[])
【输入】 int len:输入数列的长度;
int intput_array[]:输入的初始数列
int m:初始计数值
【输出】 int output_array[]:输出的数值出列顺序
【返回】 无
• 示例
输入:int input_array[] = {3,1,2,4},int len = 4, m=7
输出:output_array[] = {2,3,1,4}
1 package MyTest; 2 3 /** 4 * 约瑟夫环变种问题 5 * @author Administrator 6 * 7 */ 8 9 import java.util.*; 10 11 public class JosephPro { 12 13 static LinkedList<Integer> result = new LinkedList<>(); 14 public static void main(String[] args) { 15 Scanner in = new Scanner(System.in); 16 while(in.hasNext()){ 17 result.clear(); 18 int len = in.nextInt(); 19 int[] input_aray = new int[len]; 20 for(int i = 0; i < len; i++){ 21 input_aray[i] = in.nextInt(); 22 } 23 int m = in.nextInt(); 24 josephIterate(len, input_aray, m); 25 for(Integer o: result){ 26 System.out.println(o); 27 } 28 } 29 in.close(); 30 31 } 32 33 private static void josephIterate(int len, int[] input_aray, int m) { 34 LinkedList<Integer> array = new LinkedList<>(); 35 for(int i = 0; i < len; i++) 36 array.add(input_aray[i]); 37 int flag = 0; 38 while(array.size() > 0){ 39 flag = flag + m; 40 int i = flag % array.size() -1; 41 42 if(i<0){ 43 m = array.get(array.size()-1); 44 result.add(array.get(array.size()-1)); 45 array.remove(array.size()-1); 46 flag = 0; 47 } 48 else{ 49 m = array.get(i); 50 flag = i; //这个很重要 要及时更新开始位置flag 51 result.add(array.get(i)); 52 array.remove(array.get(i)); 53 } 54 55 } 56 } 57 58 }
注意区别一个间隔是固定的,一个是变化的。