1. 程式人生 > >孩子們的遊戲(圓圈中最後剩下的數)/簡單約瑟夫環

孩子們的遊戲(圓圈中最後剩下的數)/簡單約瑟夫環

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開始。