约瑟夫问题的理解与解决(丢手帕问题)

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;
    }
}

 

以上是关于约瑟夫问题的理解与解决(丢手帕问题)的主要内容,如果未能解决你的问题,请参考以下文章

数据结构与算法: 约瑟夫问题(丢手绢)

丢手帕问题

单向环形链表解决Josephu(约瑟夫)问题

单向环形链表解决Josephu(约瑟夫)问题

用ArrayList(解决约瑟夫问题)

scala模拟链表并解答约瑟夫问题