約瑟夫環問題

2021-10-09 04:47:56 字數 1618 閱讀 9882

直接看對應的題目:

圓圈中最後剩下的數字

0,1,n-1這n個數字排成乙個圓圈,從數字0開始,每次從這個圓圈裡刪除第m個數字。求出這個圓圈裡剩下的最後乙個數字。

例如,0、1、2、3、4這5個數字組成乙個圓圈,從數字0開始每次刪除第3個數字,則刪除的前4個數字依次是2、0、4、1,因此最後剩下的數字是3。

示例 1:

輸入: n = 5, m = 3

輸出: 3

示例 2:

輸入: n = 10, m = 17

輸出: 2

限制

思路

最簡單的思路就是直接用鍊錶模擬這個過程。對於c++而言可以用標準庫中的list,然而時間複雜度太高了,應該是o(mn)。下面的**我在力扣裡直接判斷超時了。

不過這裡還是寫一下,也算是複習list的用法,並且乙個有知識點是 list 用 erase 刪除節點,會返回後面乙個節點的迭代器。

超時的c++**

class

solution

auto it = ring.

begin()

;while

(ring.

size()

>1)

++it;

++num;}if

(it == ring.

end())

it = ring.

erase

(it)

;//list迭代器刪除會自動返回下乙個迭代器

}return

*(ring.

begin()

);}}

;

想要寫出時間複雜度低的不超時的**,還得用數學推導的方式推導出乙個遞推公式。

f(n,m) = [m+f(n−1,m)]%n

公式的證明太硬,本人幾次看懂幾次忘記,想來也是沒有真正懂,力扣題解裡有很好的證明,同時也有用影象進行演示的,因此這裡也不 詳述證明過程,只談談個人對公式的具體含義的理解:

公式的大致意思是長度為 n 的序列經過約瑟夫不停地往後刪除第 m 個元素的操作後最終留下的數值的索引 f(n,m) 可以通過長度為 n-1 的序列中最終留下的數字的索引 f(n-1,m) 計算得到。這樣我們只要不停得遞迴,算到 f(1,m),由於長度為 1 的序列最終留下的數字的索引顯然是 0,因此就能計算出最終結果。

雖然不證明,但還是最好用乙個例項加深理解(其實根本沒理解,用加深記憶更為妥當)。這裡思考示例1,示例1中最終留下是數字索引 f(n,m) = f(5,3) = 3,然後我們在紙上演算一下 f(4,3) ,發現刪除到最後留下的數字索引為 0 ,[m+f(n−1,m)]%n = (3+0)%5 = 3,這顯然是符合公式的。

上面提到遞迴,但其實用迭代方法直接倒著算就可以了。通過該方法編寫的**時間複雜度是o(n),比起上述模擬整個過程的方法大大降低。

不超時的c++**

class

solution

return res;}}

;

約瑟夫問題 約瑟夫環

約瑟夫 問題 有時也稱為約瑟夫斯置換,是乙個出現在電腦科學和數學中的問題。在計算機程式設計的演算法中,類似問題又稱為約瑟夫環。又稱 丟手絹問題 據說著名猶太歷史學家 josephus有過以下的故事 在羅馬人占領喬塔帕特後,39 個猶太人與josephus及他的朋友躲到乙個洞中,39個猶太人決定寧願死...

約瑟夫問題 約瑟夫環

約瑟夫問題 有時也稱為約瑟夫斯置換,是乙個出現在電腦科學和數學中的問題。在計算機程式設計的演算法中,類似問題又稱為約瑟夫環。又稱 丟手絹問題 據說著名猶太歷史學家 josephus有過以下的故事 在羅馬人占領喬塔帕特後,39 個猶太人與josephus及他的朋友躲到乙個洞中,39個猶太人決定寧願死也...

約瑟夫環問題

約瑟夫環問題 問題描述 編號是1,2,n的n個人按照順時針方向圍坐一圈,每個人持有乙個密碼 正整數 一開始任選乙個正整數作為報數上限值m,從第乙個人開始順時針方向自1開始順序報數,報到m時停止報數。報m的人出列,將他的密碼作為新的m值,從他在順時針方向的下乙個人開始重新從1報數,如此下去,直到所有人...