1. 程式人生 > >約瑟夫環問題:有n個人排成一列或是一圈,從編號為k的人開始報數,數到m的那個人出列。(Java實現)

約瑟夫環問題:有n個人排成一列或是一圈,從編號為k的人開始報數,數到m的那個人出列。(Java實現)

文章目錄



約瑟夫環問題

約瑟夫環描述:約瑟夫環(約瑟夫問題)是一個數學的應用問題:已知n個人(以編號1,2,3…n分別表示)圍坐在一張圓桌周圍。從編號為k的人開始報數,數到m的那個人出列;他的下一個人又從1開始報數,數到m的那個人又出列;依此規律重複下去,直到圓桌周圍的人全部出列。



1.題目

約瑟夫環問題,輸入人數n,第m個人出列,最後一個人的編號是多少?



例子:
輸入:5 3
輸出:4
例子



2.解析

1.先把這n個人按順序加進LinkedList。選擇連結串列是因為連結串列在進行大量資料插入刪除的時候會比順序表ArrayList的效率要高,而ArrayList在查詢的時候效率會相對高。

2.從索引0開始報數,到索引m-1的時候,也就是第m個人出列。

index = m - 1;  //初始化,index指向第一個出列的人
linkedList.remove(index);

3.排在這個人後面的人都向前移了一位,也就是如4的索引原來是3的,在3出列之後,隊伍裡還有[1,2,4,5]四個人,這時候4的索引變成了3-1=2,5的索引變成了4-1=3。所以新的索引就要從出列的人重新開始數,再次數到m-1。再次執行上面的刪除操作。

index += m - 1;

4.我們還會發現一個問題,就是index一直加的話,豈不是會陣列越界了?這時候該怎麼辦呢?怎麼樣才能讓一個連結串列排出一個圈的效果呢?
我們可以用 索引 % 連結串列長度

進行取餘操作

5.最後,我們總結一下。需要初始化的索引,與迴圈體內的程式碼如下:

index = m - 1;  //初始化,index指向第一個出列的人

while(linkedList != 0){
    index %= linkedList.size();
    linkedList.remove(index);
    index += m - 1;
}


3.總程式碼

private int josephRingMethod(int n, int m){

    LinkedList<Integer> linkedList = new LinkedList()
; for (int i = 1; i <= n; i++) { linkedList.add(i); } int index = m - 1; //初始化,index指向第一個出列的人 while (linkedList.size() != 0){ System.out.println(linkedList); //用 **索引 % 連結串列長度** 進行取餘操作,避免下標越界 index %= linkedList.size(); //出列 System.out.println(linkedList.get(index) + "號出列"); linkedList.remove(index); //返回最後剩下的人的編號 if (linkedList.size() == 1){ return linkedList.get(0); } //新的索引就要從出列的人重新開始數,再次數到m-1。 index += m - 1; } return -1; }