约瑟夫问题的理解与解决(丢手帕问题)
Posted 韶光不负
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了约瑟夫问题的理解与解决(丢手帕问题)相关的知识,希望对你有一定的参考价值。
又到了面试题的总结手机,下面让我们来看看如何理解与求解约瑟夫问题吧!
什么是约瑟夫问题?
简单来讲(小编个人理解):一堆人想要选择一个人来做事情(需要多个人),就选择一个数,排序到这个数的人去做这件事,然后重1开始继续排序,反复循环,直到满足条件:
为什么叫丢手帕问题?
当时解决办法比较像丢手帕(方便让人理解),让人排列成一个环,从开头开始数然后到目标,选择出来在继续数,循环反复。
解决部分
例:30个人在一条船上,超重了,要选择15人下船。商量决定排成一排,按照排列顺序给定一个编号,从1开始报数,数到4的人就下船!(反复循环,直到船上有15人结束,问有哪一些编号的人下了船?)
数组
import java.util.Scanner;
public class Joseph_problem {
public static void main(String[] args) {
int arr[]=new int[30];//创建一个30内存的数组,int数组默认全部是0.
Scanner sc=new Scanner(System.in);
System.out.println("请输入总人数:");
int n =sc.nextInt();
System.out.println("请输入报数下船编号:");
int m =sc.nextInt();
sc.close();
int count=0,j=0,k=0;//统计下船人数,i为排序的编号,k为报数编号
while (count!=n){
if (j>=n){
//当循环大于一次后,编号不变,(下标不能超出索引)
j=0;
}
for (;j < n; j++) {
//排序编号
if (arr[j]==0){
//表示人还在船上。进行报数
k++;//开始报数
if (k==m){
//当报到下船编号是,人下船
arr[j]=1;//淘汰出去
count++;
System.out.print(j+" ");
k=0;//重新开始报数
}
}
}
}
}
}
循环链表
敬请期待。。。
递归
递归公式:当第一次淘汰 i=1时:i=(k-1+n)%n
当 i!=1时:i=(ysf(n-1,k,i-1)+k)%n.
import java.util.Scanner;
public class Joseph_problem {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
System.out.println("请输入总人数:");
int n =sc.nextInt();
System.out.println("请输入出局数组k:");
int k =sc.nextInt();
sc.close();
for (int i = 1; i <= n ; i++) {
int val=ysf(n,k,i);
System.out.println("第"+i+"次淘汰的数字是:"+val);
}
}
public static int ysf(int n ,int k,int i){
if(i==1){
return (n+k-1)%n;
}else {
return (ysf(n - 1, k, i - 1) + k) % n;
}
}
}
趣味新知识
约瑟夫问题的诞生:据说在罗马帝国时期,犹太士兵被罗马人包围,犹太士兵集体自杀,自杀方式为,排列成一个圆圈,顺时针排序号,1杀2,3杀4,依次向下,当完成一个圈后,(如果1没有死还是重1开始,重新排序,如果1死了,下一个为1进行排序。)犹太士兵当中有一个人叫约瑟夫,他想投降保命,但不敢说。求一下如果你是约瑟夫,你在什么位置不会死?
1,根据第一次排序,奇数位置上的数不会死,所以必须占在奇数位置上。
2,当士兵人数为2的n次方时,1位置是不会死的。
3,方程组{ 总人数=a+2*n, 存活人位置=2a+1 }
import java.util.Scanner;
public class Joseph_problem {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
System.out.println("请输入总人数:");
int n =sc.nextInt();
int y=ysf(n);
sc.close();
System.out.println("存活的位置是:"+y);
}
public static int ysf(int n){
int y=0;
int x=1;
while (n>Math.pow(2,x)){
x++;
}
y= (int) ((n-Math.pow(2,x-1))*2+1);
return y;
}
}
以上是关于约瑟夫问题的理解与解决(丢手帕问题)的主要内容,如果未能解决你的问题,请参考以下文章