1. 程式人生 > >n個人戰成一圈,依次從0~m-1報數,誰是m-1就出圈,下一個人從0重新開始 依次迴圈下去,直到剩一人。

n個人戰成一圈,依次從0~m-1報數,誰是m-1就出圈,下一個人從0重新開始 依次迴圈下去,直到剩一人。

題目描述

每年六一兒童節,牛客都會準備一些小禮物去看望孤兒院的小朋友,今年亦是如此。HF作為牛客的資深元老,自然也準備了一些小遊戲。其中,有個遊戲是這樣的:首先,讓小朋友們圍成一個大圈。然後,他隨機指定一個數m,讓編號為0的小朋友開始報數。每次喊到m-1的那個小朋友要出列唱首歌,然後可以在禮品箱中任意的挑選禮物,並且不再回到圈中,從他的下一個小朋友開始,繼續0...m-1報數....這樣下去....直到剩下最後一個小朋友,可以不用表演,並且拿到牛客名貴的“名偵探柯南”典藏版(名額有限哦!!^_^)。請你試著想下,哪個小朋友會得到這份禮品呢?(注:小朋友的編號是從0到n-1)

/*
問題總結:n個人戰成一圈,依次從0~m-1報數,誰是m-1就出圈,下一個人從0重新開始
依次迴圈下去,直到剩一人。

思路1:利用數學歸納法總結規律
Xn表示有n個小朋友時,留在最後的小朋友的角標,m不變
則有以下規律:Xn = (Xn-1 + m) % n;//關鍵,此類問題的通解。
由以上公式,顯然利用遞迴就能求解。
*/

class Solution {
public:
    int LastRemaining_Solution(int n, int m)
    {
        if(n == 0)
            return -1;
        if(n == 1)
            return 0;
        else
            return(LastRemaining_Solution(n-1,m) + m) % n;
    }
};

/*
思路2:用陣列來模擬環
*/

class Solution {
public:
    int LastRemaining_Solution(int n, int m)
    {
       if(n<1 || m<1)
           return -1;
       vector<int> temp(n,0);
       int i = -1,step = 0,count = n,index = -1;
       while(count>0){
           i++;
           index = i % n;
           if(temp[index] == -1) continue;
           step++;
           if(step == m){
               temp[index] = -1;
               step = 0;
               count--;
           }
        }
        return index;
    }
};