n個數字(0,1,…,n-1)造成一個圓圈,從數字0開始,每次從這個圓圈中刪除第m個數字(第一個爲當前數字自己,第二個爲當前數字的下一個數字)。當一個數字刪除後,從被刪除數字的下一個繼續刪除第m個數字。求處在這個圓圈中剩下的最後一個數字。學習
(其實說了這麼多就是約瑟夫環問題)spa
之前學習鏈表的時候也見過約瑟夫環問題,當時是拿循環鏈表模擬整個過程來解決的,今天在網上看到一種分析。記錄下來:code
題目要求最後剩下的一個數(用last表示),也就是這個數是第幾個,在(0,1,…,n-1)的位置是多少。明確了題目中的信息,因此咱們要對這個數進行概括。假設知道這個數在剩下的k個數中的位置,怎麼來求得它在剩餘K+1個數中的位置,這樣一步一步推導出它在有n個數中的位置,即爲所求。爲何能這樣概括,由於這個最後剩下的數在全部刪除過程當中有幸存活下來,只不過每次刪除了一個數,它的位置就變了,知道最後,它的位置爲0(只剩一個數了)。ast
如今來分析刪除第一個數後,last這個數的位置已以前有什麼樣的關係。在這n個數字中,第一個被刪除的數字是(m-1)%n,爲簡單起見記爲k。那麼刪除k以後的剩下n-1的數字爲0,1,…,k-1,k+1,…,n-1,而且下一個開始計數的數字是k+1。至關於在剩下的序列中,k+1排到最前面,從而造成序列k+1,…,n-1,0,…k-1。class
k+1 -> 0
k+2 -> 1
…
n-1 -> n-k-2
0 -> n-k-1
…
k-1 -> n-2互聯網
如今咱們知道了有n-1個數時last的位置,記爲f(n-1,m),那麼如何來求得f(n,m)關於f(n-1,m)之間的關係?用X,Y來表示,以下:循環
Y X鏈表
k+1 -> 0
k+2 -> 1
…
n-1 -> n-k-2
0 -> n-k-1
…
k-1 -> n-2co
y=( x+k+1) %n數字
k = (m-1)%n
因此y=(x+m)%n,最終關係以下:
0 n=1
f(n,m)={
[f(n-1,m)+m]%n n>1
根據關係能夠很方便的獲得代碼
int LastRemaining(int n, int m) { if(n < 1 || m < 1) return -1; int last = 0; for (int i = 2; i <= n; i ++) last = (last + m) % i; return last; }
注:分析部份內容來自互聯網