經典演算法 約瑟夫環問題的三種解法

2021-08-20 02:05:22 字數 2440 閱讀 9443

約瑟夫環問題,這是乙個很經典演算法,處理的關鍵是:偽鍊錶

問題描述:n個人圍成一圈,從第乙個人開始報數,報到m的人出圈,剩下的人繼續從1開始報數,報到m的人出圈;如此往復,直到所有人出圈。(模擬此過程,輸出出圈的人的序號)

在資料結構與演算法書上,這個是用鍊錶解決的。我感覺鍊錶使用起來很麻煩,並且這個用煉表處理起來也不是最佳的。

我畫了乙個圖用來理解:

有如下問題需要首先考慮:

1、「圈」怎樣形成?

以上圖為例:下標從0開始,當下標為11的時候,再加1,就應該回到0。

index = (index+1) % count;
2、怎樣處理?陣列or鍊錶or其他方法?

鍊錶使用起來很笨重,我們用迴圈陣列的方法。

迴圈的開始和結束:迴圈的結束取決於圈內是否還有「人」,可以用乙個變數alive表示初始人數,每一次出圈,alive - 1。判斷alive是否非0即可。

while(alive > 0)

每一次迴圈,就是「過」乙個人,但是,這個人有兩種不同的狀態:在圈內和不在圈內;在圈內就報數,number+1,不在圈內就不參與報數,number不變。

假設有n個int元素的陣列,每乙個int元素表示乙個「人」;並且,取值為0和1, 1表示在圈內,0表示不在圈內,所以,如果這個人在圈內,number + 1;如果這個人不在圈內,number + 0。那麼,在報數的時候,不需要考慮這個人在不在圈內(每乙個人都需要加1或加0,所以,可以在這塊優化一下程式)。

void joseph(int count, int doom) 

//與總人數count取餘,則可以使index在0~count-1之間 一直迴圈,達到迴圈陣列的目的

index = (index +1) % count;

} printf("\n");

free(circle); //結束後一定要釋放circle所申請的空間

解法二在解法一的基礎上進行了優化,對出圈的人的節點進行刪除,可以減少時間複雜度。

假設,要刪除的節點下標為curindex,其前驅節點下標為preindex;

circle[preindex] = circle[curindex];
假設要刪除的節點下標curindex=3,那麼circle[2] = circle[3] ,circle[2]  = 4,circle[2]之前等於3,現在等於4。即下標為3的第四個人已經被刪除了。

怎樣遍歷?   

preindex = curindex;

curindex = circle[curindex];

但是,在出圈的時候,curindex 和preindex 的變化有別於上面的操作:

出圈時,curindex 需要後移,preindex 應該不動!

每次迴圈,直接報數,因為被刪除的人(例如上面的第四個人)不可能進行報數了。

解法三里沒有進行number報數,而是直接計算出需要移動的人數,然後定位到要出圈的人。

num = doom % alive - 1;

for(index = 0; index < (num == -1 ? alive - 1 : num); index++)

void joseph(int count, int doom) 

while(alive > 0)

// 該人出圈!

alive == 1 ? printf("%d", curindex+1) : printf("%d,", curindex+1);

alive--;

circle[preindex] = circle[curindex]; // 真正的出圈操作!

curindex = circle[curindex]; // 繼續處理下乙個人

} // 這個演算法比normaljoseph.c效率提高30%!

約瑟夫環的三種解法

有n個程式猿 編號1 n 圍成一圈順序迴圈報數,從第乙個猿開始報數 從1到4報數,猿都是順序排列成一圈的 凡報到4的猿退出圈子,以下乙個為1繼續報數,問最後留下的是原來第幾號的那位。題目的意思大致是這樣,比如最開始有五個人編號為1 2 3 4 5 第二輪起點是5,去掉3 第三輪起點是5,去掉5 第四...

約瑟夫環的三種解法

約瑟夫問題是個有名的問題 n個人圍成一圈,從第乙個開始報數,第m個將被殺掉,最後剩下乙個,其餘人都將被殺掉。n個人從1開始編號,問最後活下來的人的編號是多少。include using namespace std intmain printf 遊戲結束,所有人死亡 n return0 主要是利用遞推...

詳解基於C 實現約瑟夫環問題的三種解法

目錄 什麼是約瑟夫環問題?約瑟夫環問題在不同平台被 優化 描述的不一樣,例如在牛客劍指offer叫孩子們的遊戲,還有叫殺人遊戲,點名 最直接的感覺還是力扣上劍指offer62的描述 圓圈中最後剩下的數字。問題描述 0,1,n 1這n個數字排成乙個圓圈,從數字0開始,每次從這個圓圈裡刪除第m個數字 刪...