演算法題目 約瑟夫環問題

2021-09-25 05:37:05 字數 1167 閱讀 2563

題目:0,1,。。。,n-1這n個數字排成乙個圓圈,從數字0開始每次從這個圓圈裡刪除第m個數字。求出這個圓圈裡剩下的最後乙個數字。

解法一:經典解法,用環形鍊錶模擬圓圈。這種方法每刪除乙個數字需要m步運算,總共有n個數字,因此總的時間複雜度是o(mn).同時這種思路還需要乙個輔助鍊錶來模擬圓圈,其空間複雜度是o(n)。

int lastremaining(unsigned int n, unsigned int

m) list

::iterator next = ++iter;

--iter;

if (next ==nums.end())

next =nums.begin();

nums.erase(iter);

iter =next;

}return *iter;

}

解法二:

我們知道第乙個人(編號一定是m%n-1) 出列之後,剩下的n-1個人組成了乙個新的約瑟夫環(以編號為k=m%n的人開始):

k  k+1  k+2  ... n-2, n-1, 0, 1, 2, ... k-2並且從k開始報0。

現在我們把他們的編號做一下轉換:

k     --> 0

k+1   --> 1

k+2   --> 2

......

k-2   --> n-2

k-1   --> n-1

變換後就完完全全成為了(n-1)個人報數的子問題,假如我們知道這個子問題的解:例如x是最終的勝利者,那麼根據上面這個表把這個x變回去不剛好就是n個人情況的解嗎?!!變回去的公式很簡單,相信大家都可以推出來:x'=(x+k)%n

如何知道(n-1)個人報數的問題的解?對,只要知道(n-2)個人的解就行了。(n-2)個人的解呢?當然是先求(n-3)的情況 ---- 這顯然就是乙個倒推問題!好了,思路出來了,下面寫遞推公式:

令f[i]表示i個人玩遊戲報m退出最後勝利者的編號,最後的結果自然是f[n]

遞推公式

f[1]=0;

f[i]=(f[i-1]+m)%i;  (i>1)

#include int

main()

printf (

"\nthe winner is %d\n

", s+1

);}

演算法題目 約瑟夫環問題

題目 0,1,n 1這n個數字排成乙個圓圈,從數字0開始每次從這個圓圈裡刪除第m個數字。求出這個圓圈裡剩下的最後乙個數字。解法一 經典解法,用環形鍊錶模擬圓圈。這種方法每刪除乙個數字需要m步運算,總共有n個數字,因此總的時間複雜度是o mn 同時這種思路還需要乙個輔助鍊錶來模擬圓圈,其空間複雜度是o...

演算法 約瑟夫環問題

同步更新。歡迎移步體驗更好的閱讀效果。約瑟夫問題是個著名的問題 n個人圍成一圈,第乙個人從1開始報數,報m的將被殺掉,下乙個人接著從1開始報。如此反覆,最後剩下乙個,求最後的勝利者。例如只有三個人,把他們叫做a b c,他們圍成一圈,從a開始報數,假設報2的人被殺掉。剛學資料結構的時候,我們可能用鍊...

演算法 約瑟夫環問題

約瑟夫環 約瑟夫問題 是乙個數學的應用問題 已知n個人 以編號1,2,3.n分別表示 圍坐在一張圓桌周圍。從第乙個人開始報數,數到m的那個人出列 他的下乙個人又從1開始報數,數到m的那個人又出列 依此規律重複下去,求最後乙個出圈的人的標號。void josef int n,int m n個人,m出列...