【编程题】约瑟夫环及约瑟夫变种问题

约瑟夫环是一个数学的应用问题:已知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 }

注意区别一个间隔是固定的,一个是变化的。

原文地址:https://www.cnblogs.com/focusonepoint/p/5756773.html