據說你還不懂約瑟夫環!!!

約瑟夫環算法

問題: N我的編號爲1,2,……,N,圍成一個環,依次報數,每報到M時,殺掉那我的,求最後勝利者的編號。編程

換一下編號,如今假設有10我的編號爲a,b,c,d,e,f,g,h,i,j,M=3吧。數組

殺第一我的的結果以下數據結構

殺第二我的的時候至關於從d開始,結果以下code

最後咱們能夠知道d最終存活了下來,設f(n) = x 表示有n我的時存活下來的是x,這裏f(10)=d。blog

如今咱們來跟蹤一下d的位置變化遞歸

一開始殺第一我的時d的位置基礎

而後殺第二我的時d的位置im

看到這裏我想你應該什麼都看不出來,若是我此時問你若是隻有9我的那麼那我的存活的下標是多少你應該也是看不出來的。
這裏不是說你們笨,你們都是這樣子,一開始誰能反映的過來的啊。不用急聽我細細道來。鏈表

再看一下這個圖

咱們很容易就能夠得知最後一個是一個死人,死人是不會再被數一次的,那咱們就把最後一個死人刪掉吧。

那此時不就至關於只有9我的的狀況嗎

雖然字母順序對不上,可是若是隻看下標的話你應該可以說出9我的的時候下標是多少的人存活下來吧也就是下標爲0。

並且這個下標不是隨便來的,而是按照必定的規律出現的,也就是f(9) = f(10) - M,可能有人會問若是下標越界了咋辦啊。那還不簡單取模不就能夠了。f(n)有可能會是負數,負數取模可能比較抽象,那咱們轉換成正數取模吧(這一步是比較瓜熟蒂落的但願沒有把你困擾住) 也就是 f(10) = f(9)+M , 爲了預防越界也就是f(10) = (f(9)+M) %10; 爲何是和10取模而不是和9取模呢?這一點的是由於9我的時是由10我的經過移位再去掉最後一個死人後獲得的本質上仍是10我的,天然就是要和10取模,也能夠經過上面的圖,更好的理解這一點。

經過這個例子,想必你可以簡單的寫出遞歸式子了吧,也就是f(n) = (f(n-1)+M)%n。

全過程以下

代碼很簡單

public int f(int n,int m){
        if(n==1) return 0;
        return (f(n-1,m)+m)%n;
    }

固然這題還有其餘解法,數組法和鏈表法,這些思惟量就少一些了。

若是以爲有收穫,不妨花個幾秒鐘點個贊,歡迎關注個人公衆號玩編程地碼農,目前專一寫數據結構與算法和計算機基礎等相關知識。

相關文章
相關標籤/搜索