現在我們知道了G的索引号的變化過程,那麼我們反推一下,從 n = 7 n=7 n=7到 n = 8 n=8 n=8的過程,怎樣才能将 n = 7 n=7 n=7的排列順序變為 n = 8 n=8 n=8時的排列順序呢?我們【先把被殺掉的C補充回來,然後右移m個人,發現溢出了,再把溢出的補充在最前面】,經過這般操作後,就可以恢複到 n = 8 n=8 n=8時的排列順序了。當删除某個節點時,這個節點後面的全部節點都向前平移 m m m個距離;當恢複某個節點時,那麼全部節點都向後移動 m m m個機關,然後如果某些節點出界了,那麼就然這些節點回到前面(設目前這輪有 x x x個人,那麼如果越界的話,就讓那些越界的人 % x \%x %x就可以回到前面了)。
是以,我們可以推導出遞歸關系式 f ( 8 , 3 ) = [ f ( 7 , 3 ) + 3 ] % 8 f(8,3)=[f(7,3)+3]\%8 f(8,3)=[f(7,3)+3]%8,推廣到一般情況就是 f ( n , m ) = [ f ( n − 1 , m ) + m ] % n f(n,m)=[f(n-1,m)+m]\%n f(n,m)=[f(n−1,m)+m]%n。
約瑟夫環約瑟夫環
遞推公式:
再把
n=1
這個最初的情況加上,就得到遞推公式:
f ( n , m ) = { 0 n = 1 [ f ( n − 1 , m ) + m ] % n n > 1 f(n,m)=\begin {cases} 0 & n=1 \\ [f(n-1,m)+m]\%n & n>1 \end{cases} f(n,m)={0[f(n−1,m)+m]%nn=1n>1
約瑟夫環約瑟夫環
約瑟夫環約瑟夫環
代碼
class Solution {
public:
int lastRemaining(int n, int m) {
int pos = 0; // 最終活下來那個人的初始位置
//i表示這一輪的人數 一直做到最初有n個人時 最終勝利者的位置
for(int i = 2; i <= n; i++)
{
pos = (pos + m) % i; // 每次循環右移
}
//這題的編号是從0開始,是以直接傳回數組下标pos就是正确的編号
//如果題目的編号是從1開始,但是由于我們的數組下标是從0開始,那麼此時輸出答案時就要數組下标pos+1,才能轉成編号
return pos;
}
};