場景:編程
一羣猴子排成一圈,按1,2,…,n依次編號。而後從第1只開始數,數到第m只,把它踢出圈,從它後面再開始數, 再數到第m只,在把它踢出去…,如此不停的進行下去, 直到最後只剩下一隻猴子爲止,那隻猴子就叫作大王。要求編程模擬此過程,輸入m、n, 輸出最後那個大王的編號。數組
方法1.經過從隊首彈出再插入隊尾的方法。注意雖然這種方法使猴子的編號看似發生變化了,但其實到最後編號仍是正確的,就是不用擔憂編號變化的問題。能夠本身畫一畫就知道了。spa
function king($n,$m) { $monkey = range(1,$n);//模擬創建一個連續數組 $i = 0; while(count($monkey) > 1) { $i ++ ; // 開始查數 $head = array_shift($monkey); //直接一個一個出列最前面的猴子 if($i % $m != 0) { array_push($monkey,$head); // 若是沒數到m或m的倍數,則把該猴放回尾部去. } //不然就拋棄掉了 } return $monkey[0]; } //echo '剩餘',king(3,4),'號猴子'; #2 echo '剩餘',king(6,9),'號猴子'; #
方法2.經過分析得出一個公式。code
每一個猴子出列後,剩下的猴子又組成了另外一個子問題。只是他們的編號變化了。第一個出列的猴子確定是a[1]=m(mod)n(m/n的餘數),他除去後剩 下的猴子是a[1]+1,a[1]+2,…,n,1,2,…a[1]-2,a[1]-1,對應的新編號是1,2,3…n-1。設此時某個猴子的新編號是 i,他原來的編號就是(i+a[1])%n。因而,這便造成了一個遞歸問題。假如知道了這個子問題(n-1個猴子)的解是x,那麼原問題(n個猴子)的解 即是:(x+m%n)%n=(x+m)%n。問題的起始條件:若是n=1,那麼結果就是1。blog
function king($n,$m) { $r=0; for($i=2; $i<=$n; $i++) { $r=($r+$m)%$i; } return $r+1; } echo king(10,3)."是猴王";