孩子們的遊戲(圓圈中最後剩下的數)/簡單約瑟夫環
阿新 • • 發佈:2018-12-09
1.數學遞推,遞迴,時間複雜度O(n)
結論:
分析:
下面用數學公式推導的方法,解決約瑟夫環經典問題。
第一步,這n個人我們給每一個人一個編號 0 ,1 ,2 ······ n-2,n-1
第二步,當第一輪遊戲結束後,這n個人少就變成了n-1個人
第三步,將第一輪結束後剩下的人裡面第一個報數的記為m,則這n-1個人 的編號為
m,m+1,m+2······n-2,n-1,0,1,2,······m-2(m-1也就是第一輪結束後出局的那個人)
第四步,也是最關鍵的一步,這n-1個人我們是不是也可以當成第一步那樣重新來個編號,如下:
m,m+1,m+2······n-2,n-1,0, 1, 2,······m-2 0 ,1 ,2 ······ n-m n-3,n-2(少了一個人所以到n-2)
第五步 我們來推導數學公式。假設有n個人時,最後剩下的人的編號為f(n).
- 在四步的轉換中k - -> 0,那麼當我們從反過來從發f(n-1)的情況推f(n)的情況的時候,如果在n-1情況下f(n-1)是最後勝出的人,那麼在n的情況下 f(n-1)+m就是最後勝出的人。
由此,得出公式f(n)=(f(n-1)+m)%n
,f(1)=0.
兩種形式實現遞推
1.迴圈
class Solution {
public:
//約瑟夫環
int LastRemaining_Solution(int n, int m)
{
if(! n&&!m)return -1;
int lastpeople=0;
for (int i = 2; i <= n; i++)
{
lastpeople = (lastpeople + m) % i;
}
return lastpeople;
}
};
2.遞迴
class Solution {
public:
//約瑟夫環
int LastRemaining_Solution(int n, int m)
{
if (!n&&!m) return -1;
else if (n == 1)return 0;
else return (LastRemaining_Solution(n - 1, m) + m) % n;
}
};
參考這篇部落格程式碼有誤,應該i=2
開始。