约瑟夫出圈问题 两种方法实现,数据和链表 n个人围成一个圈,一个个首尾相连的圈报数,从第一个开始报数
报到m的人出圈,剩下的人继续从1开始报数,直到所有人都出圈为止。
- import java.util.LinkedList;
- import java.util.Scanner;
- /**
- * 约瑟夫出圈问题 两种方法实现,数据和链表 n个人围成一个圈,一个个首尾相连的圈报数,从第一个开始报数
- * 报到m的人出圈,剩下的人继续从1开始报数,直到所有人都出圈为止。
- *
- * @author sesame.yangj
- */
- public class Joseph {
- /**
- * @param args
- */
- public static void main(String[] args) {
- Joseph j = new Joseph();
- System.out.println("约瑟夫出圈");
- System.out.println("输入人数:");
- Scanner s = new Scanner(System.in);
- int n = s.nextInt();
- System.out.println("输入出圈的位置:");
- int m = s.nextInt();
- System.out.println("数组实现");
- j.arrayJoseph(n, m);
- System.out.println("链表实现");
- j.listJoseph(n, m);
- }
- /**
- * 用数组实现
- *
- * @param n 总的人数
- * @param m 当前报的数
- */
- public void arrayJoseph(int n, int m) {
- //数组存储编号
- int array[] = new int[n];
- int len = n;
- for (int i = 0; i < array.length; i++) {
- array[i] = i + 1;
- }
- int i = 0;
- //当前报的数
- int j = 1;
- while (len > 0) {
- if (array[i % n] > 0) {
- //位置有人
- if (j % m == 0) {
- //报到出圈的人
- System.out.println(array[i % n]);
- //为之置空
- array[i % n] = -1;
- //从1开始报数
- j = 1;
- i++;
- len--;
- } else {
- i++;
- j++;
- }
- } else {
- //遇到空位
- i++;
- }
- }
- }
- /**
- * 用双向链表实现
- *
- * @param n
- * @param m
- */
- public void listJoseph(int n, int m) {
- LinkedList<Integer> list = new LinkedList<Integer>();
- for (int i = 0; i < n; i++) {
- //添加数据,与编号对应
- list.add(i + 1);
- }
- int moved = 0;
- while (list.size() > 0) {
- moved = (moved + m - 1) % list.size();
- System.out.println(list.get(moved));
- list.remove(moved);
- }
- }
- }
- public class Joseph {
- /**
- * 问题描述
- * 约瑟夫问题:有n只猴子,按顺时针方向围成一圈选大王(编号从1到n),从第1号
- * 开始报数,一直数到m,数到m的猴子退出圈外,剩下的猴子再接着从1 开始报数。就这样,
- * 直到圈内只剩下一只猴子时,这个猴子就是猴王,编程求输入n,m后,输出最后猴王的编号。
- * 输入数据
- * 每行是用空格分开的两个整数,第一个是 n ,第二个是 m ( 0 < m, n < 300),最后一行是:0 0
- * 输出要求
- * 对于每行输入数据(最后一行除外),输出数据也是一行,即最后猴王的编号
- * 输入样例:
- * 6 2
- * 12 4
- * 8 3
- * 0 0
- * 输出样例:
- * 5
- * 1
- * 7
- */
- public static void main(String[] args) {
- Scanner in =new Scanner(System.in);
- System.out.print("有几只猴子选大王?");
- int amount = in.nextInt();
- System.out.print("喊几的退出圈子?");
- int num = in.nextInt();
- // 定义"猴子圈"
- Set<Integer> monkeys = new TreeSet<Integer>();
- // 初始化"猴子圈",确定每只猴子的编号。
- for (int i = 1; i <= amount; i++) {
- monkeys.add(i);
- }
- // 初始化报的数为1
- int i = 1;
- // 开始报数! 每一轮报数,都接着上次报的数i进行,"猴子圈"只剩1只猴子了就停止报数
- while (monkeys.size() > 1) {
- // 定义猴子编号数组,用于迭代"猴子圈"
- Integer[] monkeyNums = monkeys.toArray(new Integer[0]);
- // 迭代"猴子圈",作为一轮报数
- for (int monkeyNum : monkeyNums) {
- if (i < num) {
- // 下只猴子要报的数
- i++;
- } else {
- // 如果这只猴子报的数是num,就把它移出"猴子圈"
- monkeys.remove(monkeyNum);
- // 下只猴子报数从1开始
- i = 1;
- }
- }
- }
- // "猴子圈"的最后一只猴子做大王。
- int king = 0;
- for (int monkeyNum : monkeys) {
- king = monkeyNum;
- }
- System.out.println("大王是" + king + "号猴子");
- }
- }