首頁>Club>
求解報數問題。設有n個人佔成一排,從左向右的編號分別為1到n,現在從左往右報數“1,2,1,2…”,數到1的人出列,數到2的人立即站到隊伍的隊尾。報數過程反覆進行,直到n個人都出列為止。要求給出他們的出列順序。請大神幫忙程式設計!謝謝!
19
回覆列表
  • 1 # 五分鐘學演算法

    這個問題就是『約瑟夫環』問題嘛。

    1 問題描述

    約瑟夫環(約瑟夫問題)是一個數學的應用問題:已知 n 個人(以編號1,2,3...n分別表示)圍坐在一張圓桌周圍。從編號為 k 的人開始報數,數到 m 的那個人出圈;他的下一個人又從 1 開始報數,數到 m 的那個人又出圈;依此規律重複下去,直到剩餘最後一個勝利者。

    例如:有10個人圍成一圈進行此遊戲,每個人編號為 1-10,。若規定數到 3 的人出圈。則遊戲過程如下。

    (1)開始報數,第一個數到 3 的人為 3 號,3 號出圈。   1, 2, 【3】, 4, 5, 6, 7, 8, 9, 10。 (2)從4號重新從1開始計數,則接下來數到3的人為6號,6號出圈。   1, 2, 【3】, 4, 5, 【6】, 7, 8, 9, 10。 (3)從7號重新從1開始計數,則接下來數到3的人為9號,9號出圈。   1, 2, 【3】, 4, 5, 【6】, 7, 8, 【9】, 10。 (4)從10號重新從1開始計數,由於10個人稱環形結構,則接下來數到3的人為2號,2號出圈。   1, 【2】, 【3】, 4, 5, 【6】, 7, 8, 【9】, 10。 (5)從4號重新從1開始計數,則接下來數到3的人為7號,7號出圈。   1, 【2】, 【3】, 4, 5, 【6】, 【7】, 8, 【9】, 10。 (6)從8號重新從1開始計數,則接下來數到3的人為1號,1號出圈。   【1】, 【2】, 【3】, 4, 5, 【6】, 【7】, 8, 【9】, 10。 (7)從4號重新從1開始計數,則接下來數到3的人為8號,8號出圈。   【1】, 【2】, 【3】, 4, 5, 【6】, 【7】, 【8】, 【9】, 10。 (8)從10號重新從1開始計數,則接下來數到3的人為5號,5號出圈。   【1】, 【2】, 【3】, 4, 【5】, 【6】, 【7】, 【8】, 【9】, 10。 (9)從10號重新從1開始計數,則接下來數到3的人為10號,10號出圈。   【1】, 【2】, 【3】, 4, 【5】, 【6】, 【7】, 【8】, 【9】, 【10】。 (10)最終剩餘 4 號,4 號為勝利者。

    2 陣列求解2.1 解題思想

    用陣列求解的基本思想就是用一個一維陣列去標識這 n 個人的狀態,預設全為 1 ,也就是都在圈子內,當數到 m的人出圈之後,標識置為 0(就是出圈了),同時報數器清 0,下一個人要從 1 開始。在每次報數之前要判斷他是否在圈子內(也就是他的標識是否為 1 ),如果在圈子裡面才會繼續報數。定義一個變數記錄出圈的人數, 出圈的人數等於 n-1 時,則遊戲結束。

    2.2 程式碼實現3 迴圈連結串列求解3.1 解題思想

    約瑟夫環問題可以轉化為迴圈連結串列的資料結構來求解。可以將每個人看做連結串列的單個節點,每個節點之間透過連結串列的 next 指標連線起來,並且將連結串列末尾節點指向頭節點就形成的環,由連結串列構成的環形結構在資料結構中稱為迴圈連結串列。

    3.2 程式碼實現4 遞推公式求解4.1 解題思想

    約瑟夫環中,每當有一個人出圈,出圈的人的下一個人成為新的環的頭,相當於把陣列向前移動 m 位。若已知 n-1 個人時,勝利者的下標位置位 f(n−1,m) ,則 n 個人的時候,就是往後移動 m 位,(因為有可能陣列越界,超過的部分會被接到頭上,所以還要模 n ),根據此推導過程得到的計算公式為:   f(n,m) = (f(n−1,m) + m) % n。 其中,f(n,m) 表示 n 個人進行報數時,每報到 m 時殺掉那個人,最終的編號,f(n−1,m) 表示,n-1 個人報數,每報到 m 時殺掉那個人,最終勝利者的編號。有了遞推公式後即可使用遞迴的方式實現。

    4.2 遞迴程式碼實現

    4.3 迭代程式碼實現

    實際應用

    比如你們公司需要團建,你可以設計這個遊戲,根據遊戲人數的多少,將你和你心儀的妹子安排在合適的座位上,一同進最後的決賽圈~

  • 中秋節和大豐收的關聯?
  • 地圖要素是什麼?