【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時表示已經選出最終數。

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