**:
約瑟夫環問題是一道經典的資料結構題目
問題描述:n個人(編號0~(n-1)),從0開始報數,報到(m-1)的退出,剩下的人繼續從0開始報數。
求勝利者的編號
。一般我們採用乙個迴圈佇列來模擬約瑟夫環的求解過程,但是如果n比較大的時候,採用模擬的方式求解,需要大量的時間來模擬退出的過程,而且由於需要占用大量的記憶體空間來模擬佇列中的n個人,並不是乙個很好的解法。
在大部分情況下,我們僅僅需要知道最後那個人的編號,而不是要來模擬乙個這樣的過程,在這種情況下,可以考慮是否存在著一種數學公式能夠直接求出最後那個人的編號。
我們知道第乙個人(編號一定是m%n - 1
) 出列之後,剩下的n-1個人組成了乙個新的約瑟夫環(以編號為k=m%n的人開始):
我們先看第乙個人出列後的情況,顯而易見,第乙個出列的人的編號一定是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-1 (
k-2--n-2 by orc
)可以看出,這就是原問題中把n替換成n-1的情況,假設我們已經求出來在這種情況下最後勝利的那個人的編號是x,那個倒推回去的那個人的編號就正好是我們要求的答案,顯而易見,這個編號應該是(x+k)%n
那麼如何知道n-1個人下面的這個x呢,yes,就是n-2個人情況下得到的x'倒推回去,那麼如何知道n-2情況下的x'呢,當然是求n-3個人,這就是乙個遞迴的過程
f(1) = 0(f(1)就是現在還剩下1個人,那麼無論m為幾,這個人總會出列,因此f(1)=0)
f(n) = (f(n-1)+m)%n
那麼我們要求f(n),就從f(1)倒推回去即可
int f(int n, int m)
這種方法比模擬的方法快多了,我們在碰到問題的時候,可以想一想是否有數學公式來求解
約瑟夫環數學解法
無論是用鍊錶實現還是用陣列實現都有乙個共同點 要模擬整個遊戲過程,不僅程式寫起來比較煩,而且時間複雜度高達o nm 當n,m非常大 例如上百萬,上千萬 的時候,幾乎是沒有辦法在短時間內出結果的。我們注意到原問題僅僅是要求出最後的勝利者的序號,而不是要讀者模擬整個過程。因此如果要追求效率,就要打破常規...
約瑟夫環 數學解法
約瑟夫環是乙個數學的應用問題 已知n個人 以編號1,2,3 n分別表示 圍坐在一張圓桌周圍 從編號為k的人開始報數,數到m的那個人出列 他的下乙個人又從1開始報數,數到m的那個人又出列 依此規律重複下去,直到圓桌周圍的人全部出列。f 1 0 f i f i 1 m i i 1 includeusin...
約瑟夫環的數學解法
約瑟夫環問題是一道經典的資料結構題目 問題描述 n個人 編號0 n 1 從0開始報數,報到 m 1 的退出,剩下的人繼續從0開始報數。求勝利者的編號。一般我們採用乙個迴圈佇列來模擬約瑟夫環的求解過程,但是如果n比較大的時候,採用模擬的方式求解,需要大量的時間來模擬退出的過程,而且由於需要占用大量的記...