约瑟夫环问题
来源:互联网 发布:手机uvz阅读器软件 编辑:程序博客网 时间:2024/06/01 10:37
约瑟夫环是一个数学的应用问题:已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围。从编号为k的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列。
在这里我们可以先不考虑从第几个人开始报数,默认是从1开始报数,求出最后退出的人的编号后,再根据开始报数的编号k求,从编号为k的人开始报数,最好退出人的编号
1、非递归求解,利用boolean类型数组,模拟报数的过程,数到m的人赋值为flase
// 传入参数为总人数n和报到m时退出的数,开始为数组默认赋值都为true,返回的数组中只有一个truepublic static boolean[] doCall(int person, int exitNum) {boolean[] persons = new boolean[person];int number = person, key = 0;for (int i = 0; i < person; i++) {persons[i] = true;}while (number != 1) {for (int i = 0; i < person; i++) {if (!persons[i]) {// 已经为false不需要执行,只是保留当前位置continue;} else {key++;if (key % exitNum == 0) {persons[i] = false;number--;}}}}return persons;}2、递归求解,根据每报到m时,人数就会少1个推理
假设m=2
f(1)=0
f(2)=0=(f(1)+2)%2
f(3)=2=(f(2)+2)%3
...
f(n)=(f(n)+2)%n
public static int byRecursive(int allPersons, int exitNum) {int result = 0;for (int i = 2; i <= allPersons; i++) {result = (result + exitNum) % i;}return result;}
根据从第一个开始叫,算出最后一个未退出的人位置后,再根据第k个开始叫的人,求解最后一个未退出的人位置
// 默认是从第一个人开始叫的,我们还需要根据从第几个人开始叫的来求最后活着的人编号public static int livePersonNum(int startCallNum, int allPersons,int liveNum) {if ((liveNum + startCallNum) > allPersons) {return (liveNum + startCallNum) % allPersons;} else {return liveNum + startCallNum;}}完整代码如下:
package com.jason.algorithm;import java.util.ArrayList;import java.util.Scanner;/** * 约瑟夫环问题 约瑟夫环是一个数学的应用问题:已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围。从编号为k的人开始报数,数到m的那个人出列; * 他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列。 * * @author Jason * */public class DeletePersonByThree {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);while (scanner.hasNext()) {int inputPersonNum = scanner.nextInt();int exitNum = scanner.nextInt();int startCallNum = scanner.nextInt();if (startCallNum > inputPersonNum && startCallNum < 1) {System.out.println("the start number must >1 &<"+ inputPersonNum);return;}if (inputPersonNum < 1) {return;} else {boolean[] persons = doCall(inputPersonNum, exitNum);for (int i = 0; i < persons.length; i++) {if (persons[i]) {System.out.println("live people number :"+ livePersonNum(startCallNum,inputPersonNum, i));}}System.out.println("=============");System.out.println("live people number :"+ livePersonNum(startCallNum, inputPersonNum,byRecursive(inputPersonNum, exitNum)));break;}}}// 默认是从第一个人开始叫的,我们还需要根据从第几个人开始叫的来求最后活着的人编号public static int livePersonNum(int startCallNum, int allPersons,int liveNum) {if ((liveNum + startCallNum) > allPersons) {return (liveNum + startCallNum) % allPersons;} else {return liveNum + startCallNum;}}public static int byRecursive(int allPersons, int exitNum) {int result = 0;for (int i = 2; i <= allPersons; i++) {result = (result + exitNum) % i;}return result;}// 传入参数为总人数n和报到m时退出的数,开始为数组默认赋值都为true,返回的数组中只有一个truepublic static boolean[] doCall(int person, int exitNum) {boolean[] persons = new boolean[person];int number = person, key = 0;for (int i = 0; i < person; i++) {persons[i] = true;}while (number != 1) {for (int i = 0; i < person; i++) {if (!persons[i]) {// 已经为false不需要执行,只是保留当前位置continue;} else {key++;if (key % exitNum == 0) {persons[i] = false;number--;}}}}return persons;}}
0 0
- 约瑟夫问题、约瑟夫环
- Josephus约瑟夫环问题
- 约瑟夫环问题
- 约瑟夫环问题(Josephus)
- 约瑟夫环问题--java
- 约瑟夫环问题 Josephus
- 约瑟夫环问题
- 约瑟夫环问题
- 约瑟夫环问题
- 约瑟夫环问题
- 约瑟夫环问题
- 求解约瑟夫环问题
- 约瑟夫环问题
- 约瑟夫环问题
- 约瑟夫环问题
- 约瑟夫环问题
- 约瑟夫环问题
- 约瑟夫环问题
- 用mycat做读写分离:基于 MySQL主从复制
- Android自定义控件
- 17.03.04 泛型
- MongoDB 3.4 高可用集群搭建(三)shard 分片
- java常用的几种线程池比较
- 约瑟夫环问题
- jdk 、 tomacat 的配置
- poj-1062(昂贵的婚礼)
- 【DirectX】学习笔记(一)
- js中的字符串数字比较问题
- 关于Python相对路径的两三句话
- Java中的各种锁
- JavaScript——学习笔记(二)
- C++中对类和对象基础理解