約瑟夫環作為乙個數學問題,它的**實現方式有很多,比如迴圈鍊錶,公式解決或者動態規劃,之前參考資料也有用遞迴解決的。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.圓圈中最後剩下的數字正是約瑟夫環問題,題目如下。思路一 迴圈鍊錶法 在我們學習基礎的資料結構時,迴圈鍊錶可謂是專為約瑟夫環問...