約瑟夫環問題分析-C語言經典面試題


  好久沒有看有關算法的問題了,今天廢了不少勁,再感嘆一句:要想學好算法就要常練習,沒什么捷徑可走。廢話不多說,如下:

  問題描述:有m個人,圍成一個環,編號為 0、1、2、3、、、m-1,從第一個人開始循環報數,假設數到n的那個人出列,然后從下一個人繼續數數,數到n出列,以此循環,最后那個人為勝利者,求勝利者的編號。
  分析如下:
設m為人的個數 n為要數的數 k為從第幾個人開始數
第一次的數列,記為A
0 1 2 3 4 5 6 7 8 9 、、、n%m k、、、m-2 m-1
假設第一次出列了一個人,則編號肯定為n%m-1(減1因為從零開始)。k=n%m,第一次出列后的數列為
0 1 2 3 4 5 6 7 8 9 、、、k、、、m-2 m-1
第二次從k開始數數那么可以組成新的數列,記為數列B
k->0
k+1->1
k+2->2
k+3->3



k-3->m-3
k-2->m-2
如果我們知道了數列B的最終勝利者是的編號是x,那么x在原來數列A中的編號是多少呢?很容易算出來:(x+k)%m,而k=n%m,替換后為(x+n%m)%m=(x+n)%m,(x+n)%m為數列A的勝利者。那么x又該如何求呢,我們可以求數列C,就這樣這么以次類推。直到只有一個人時,勝利者的編號肯定為0.
假設f(y)為勝利者:則有
f(1)=0;
f(2)=(f(1)+n)%2;
f(y)= (f(y-1)+n)%y;(公式) y為數列的人數  n為要數的數

以下為編程實現,將f(y)替換為number   y替換為i

/*********************************************************************** 
**m總人數,則標號為0~m-1   n為要數的數 
**成功返回序號1~m,失敗返回-1 
***********************************************************************/  
int winner(int m, int n)  
{  
    int i;  
    int number;  
    if (m <= 0 || n <= 0) {  
        return -1;  
    }  
    number = 0;                        /* 當只有一個人時,編號為0的出圈 */  
    for (i = 2;i <= m;i++) {           /* 循環m-1次將剩下一個人         */  
        number = (number + n % i) % i; /* 這樣寫易理解,或(number+n)%i  */  
    }  
    return number + 1;                 /* 程序從0編號,返回時應+1       */  
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM