約瑟夫環(鍊錶法,公式法)

2021-08-29 09:36:32 字數 1601 閱讀 7545

約瑟夫環作為乙個數學問題,它的**實現方式有很多,比如迴圈鍊錶,公式解決或者動態規劃,之前參考資料也有用遞迴解決的。anyway,這些都是解決約瑟夫環問題很有效的方法。這裡總結兩種方法,迴圈鍊錶法和公式法。

首先是迴圈鍊錶法,它的原理很簡單,也很容易理解。求解過程和人思考解決的過程很接近。設總人數為n,報數為m的人淘汰。第一步就是建立乙個迴圈鍊錶,這樣就把從1到n的資料頭尾連線起來了,第二部就是去迴圈報數,報數為m的進行鍊錶的刪除操作。迴圈條件是總人數n!=1,即只要剩下的總人數不為1,就一定沒有迴圈結束。最後輸出指標指向那個節點的數就ok了。

要注意的問題:

1:設定乙個judge來專門進行報數以及判斷是否要刪除當前節點。因為每刪除乙個數後,就要重新從1開始報數,即judge的值重置為1。也可以在判斷時對judge取餘看結果是否為0來確定是否需要刪除,這種方法則不需要重置judge.

2:如果有頭結點,設定初始指標時應指向head->next而不是指向head,因為此時head並沒有實際意義,資料是從head->next開始儲存的,包括再建立迴圈鍊錶時,最後的指標也要指向head->next。

3:由於建立的是單向鍊錶,所以只能檢索當前節點的下乙個而不能回溯。因此在刪除操作時應提前一步進行刪除。舉個例子,假如報數為3的淘汰,當前節點如果已經檢索到3這個位置,應把2號為與4號相連來刪除3號,但當前為3號為且不能回溯,因此這樣就gg了。解決方法就是我們提前判斷,在當前節點時就判斷3要被淘汰,直接把當前節點與44號連線,即當前的next->next。

以下是**實現。

#include.h>

using namespace std;

struct listnode

;class

list

void

josephus()

;void

display()

;};void list:

:josephus()

r->next=head-

>next;

listnode *p1=head-

>next;

int judge=1;

while

(count!=1)

else p1=p1-

>next;

judge++;}

cout<<

"倖存者是"

<>date<<

"號"<}int main()

至於公式法就so easy了。按照公式f(n,m)=(f(n-1,m)+m)%n進行就ok。n為總人數,m為要被淘汰的數。具體函式實現有兩種:遞迴和迴圈。至於公式為什麼成立,怎麼得到的。好多博主寫的相當好,這裡就不在贅述了。

以下是**實現。

#include.h>

//公式法解決約瑟夫環

using namespace std;

intcir

(int n,

int m)

//迴圈實現

return p+1;

}int

cir(

int n,

int m)

//遞迴實現

intmain()

以上。

約瑟夫環公式法解釋

公式法 f n,m f n 1,m m n f 1,m 0 索引從0開始 f是每一輪中存活的人對應的編號。遞推過程如下 設編號為2的出局 即m 3 已知f 1,m 0,即只有乙個人的隊伍中,存活的肯定是編號0 從最後一輪f 1,m 求解倒數第二輪f 2,m 倒數第二輪有兩個人,殺掉乙個人後剩餘一人 ...

約瑟夫問題(迴圈鍊錶法和公式法)python版

n個人站在乙個等待被處決的圈子裡。第乙個人從1開始報數,報m的將被殺掉,下乙個人接著從1開始報。如此反覆,最後剩下乙個人就是最後的勝利者。輸入 n,m。其中n為總人數,依次編號為0,1 n,m為被處決的報數數值。輸出 最後活下來人的編號。用迴圈單鏈表去模擬這個過程。n個人看做n個鍊錶節點,節點1的v...

leetcode之約瑟夫環問題,妙哉公式法

約瑟夫環問題是n個人圍成一圈,從第乙個人開始報數,報到m的人出圈,剩下的人繼續從1開始報數,報到m的人出圈 如此往復,直到最後只剩下1個人。而今天的leetcode面試題62.圓圈中最後剩下的數字正是約瑟夫環問題,題目如下。思路一 迴圈鍊錶法 在我們學習基礎的資料結構時,迴圈鍊錶可謂是專為約瑟夫環問...