「約瑟夫環」是一個數學的應用問題:一羣猴子排成一圈,按1,2,…,n依次編號。而後從第1只開始數,數到第m只,把它踢出圈,從它後面再開始數, 再數到第m只,在把它踢出去…,如此不停的進行下去, 直到最後只剩下一隻猴子爲止,那隻猴子就叫作大王。要求編程模擬此過程,輸入max、size, 輸出最後那個大王的編號。編程
對於這個問題,能夠這麼解:每次有猴子出列後,就給全部猴子從新編號;首先第一個出列的猴子編號NO1=(size % max)==0 ? max : (size % max)(做判斷是由於size%max=0的時候,size等於max,此時編號爲0,顯然編號是不會等於0的,此時的編號應該是max),當第i個猴子出列後,那麼從它下一個猴子開始,剩下的猴子它們的新編號應該是1,2,3.....max-1,原編號是i+1,i+2...i-1。而且,當只剩最後一隻猴子的時候,此時它的新編號絕對是1; 經過觀察可知,猴子的編號是與size有關的,如圖下:max=6,size=3,括號裏的是新編號spa
而後咱們發現了一個現象,新編號和原編號的差的絕對值是size=3。也就是說,編號的變化是與size有關的。blog
而後咱們能夠概括出,假設某個猴子的新編號是i,那麼它原來的編號就是(i+size)%max,且當i+size=max時,這時它原先的編號應該爲max;如新編號 i=1,原來的編號=(i+3)%6=4;i=3,新編號爲i=3,原來的編號=(i+3)%6=0,則編號爲6。遞歸
假如知道了還剩下某個猴子的當前編號爲currentNo=x,那麼該猴子上一輪的編號previousNo=(x+size)%previousMax(注意:這裏的previousMax等於上一輪猴子的總數),且當(x+size)=max時,previousNo=max。數學
而後咱們能夠用到遞歸的思想,咱們能夠從只剩1個猴子開始推導,由於咱們知道最後一隻猴子的新編號絕對是1,而後一直獲取它上一次的編號,直到previousMax等於原來的總數Max。io
代碼:function
public function yuesefu($max, $size)
{
$index = 1;//猴子的原編號(從1開始),由於這個當只剩最後一隻猴子的時候,它的編號必定爲1.
//i—>上一輪的總猴子數
for ($i = 2; $i <= $max; $i++) {
//每循環一次,就獲取一次上一輪的編號,$i+1
$index = ($index + $size) % $i;
//當編號和猴子總數相等,此時編號應該設置爲總數
if($index==0){
$index=$i;
} } return $index;//該剩下的猴子一開始的編號。}