【Java】约瑟夫Joseph环问题(丢手绢、猴子选大王问题)

约瑟夫问题:
据说著名犹太历史学家 Josephus有过以下的故事:在罗马人占领乔塔帕特后,39 个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被敌人抓到,于是决定了一个自杀方式,41个人排成一个圆圈,由第1个人开始报数,每报数到第3人该人就必须自杀,然后再由下一个重新报数,直到所有人都自杀身亡为止。

猴子选大王问题:
100 只猴子坐成一个圈,从1开始报数,报到第14的那只猴子退出圈外,并重新开始计数。依次循环下去,直到圈中只剩下一一只猴子,就是大王。这个问题其实是一个特例,将其中的100 和14 换成变量n和m,就是约瑟夫环问题。


这是一类相同的问题。
代码如下:

import java.util.Iterator;
import java.util.LinkedList;

public class Joseph {
    public static void main(String[] args){
        //创建一个循环链表
        LinkedList<Integer> linkedList=new LinkedList<>();
        int number,cnt;   //定义两个变量,用来计数
        int target=10;     //报出编号为target的人退出

        //将数的编号放入链表中
        for(number=1;number<=100;++number){
            linkedList.addLast(number);
        }
        cnt=100;
        number=0;
        Iterator it=linkedList.iterator();
        //循环删除退出的,知道只剩一个
        while (cnt>1){
            if(it.hasNext()){
                it.next();
                number++;
            }else {
                it=linkedList.iterator();  //到尾部时,将其重新置回到链表头部
            }
            //删除符合要求的
            if(number==target){
                number=0;
                it.remove();
                cnt--;
            }
        }
        System.out.println("最终编号为:"+linkedList.element());

    }
}

这里用链表(LinkedList)来解决这个问题。将每个人的编号存入到链表的一个节点中, 将这些点组成个链表。
为了让它围成一个圈,编程的时候需要稍微处理一下,用一个迭代器示每次到达链 表尾部的时候,又重新回到链表的头部来。
可以用一个计数器number模拟报数,等于14时,就将指向的节点删除,表示此人要退出圈外,另外,还要一个计数器cnt记录已经删除的节点数,初值为100,当它为1时表示已经选出最终数。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章