leetcode之約瑟夫環問題,妙哉公式法

2021-10-23 01:43:19 字數 1798 閱讀 4106

約瑟夫環問題是n個人圍成一圈,從第乙個人開始報數,報到m的人出圈,剩下的人繼續從1開始報數,報到m的人出圈;如此往復,直到最後只剩下1個人。而今天的leetcode面試題62. 圓圈中最後剩下的數字正是約瑟夫環問題,題目如下。

思路一:迴圈鍊錶法

在我們學習基礎的資料結構時,迴圈鍊錶可謂是專為約瑟夫環問題而生,其實這是該問題的暴力法版本,我們用乙個迴圈鍊錶儲存題目中的n個人,然後開始刪除第m%n個人,迴圈往復直到剩下最後乙個人即可。

時間複雜度為o(nm),效能較差。並且考慮到golang中沒有現成的鍊錶結構可供使用,所以多少還是不方便答題。

思路二:公式法

由於需要環狀結構,我們使用陣列展示時,會在m>n時,展示多個複製的陣列以表示環狀。以[0,1,2,3,4]舉例,m為3。

第一輪 [0 1 《2》3 4]

[0 1 2 3 4]

第二輪 [3 4 《0》1]

[3 4 0 1]

第三輪 [1 3 《4]

[1 3 4]

第四輪 [1 3]

[《1》3]

第五輪 [3]

其中《》中的數字為每次被刪除的數字。

最後剩下的數字3下標是0。那麼我們從後往前推一下。

第四輪時,補上m個位置,陣列大小是2,那麼3對應的下標是(0+3)%2 = 1

第三輪時,補上m個位置,陣列大小是3,那麼3對應的下標是(1+3)%3 = 1

第二輪時,補上m個位置,陣列大小是4,那麼3對應的下標是(1+3)%4 = 0

第一輪時,補上m個位置,陣列大小是5,那麼3對應的下標是(0+3)%5 = 3

由此我們可以得出反推的公式

f(n,m)表示陣列大小為n時,每次剔除第m個元素後剩下的那乙個元素的序號。

f(n,m)

=(f(n-1,m) + m) % n

至於實現的方式,我們可以從n到0使用遞迴,也可以從2(舉例中的陣列大小為2開始)到n,使用迭代。

使用迭代的複雜度如下:

時間複雜度:o(n),需要求解的函式值有 n 個。

空間複雜度:o(1),只使用常數個變數。

使用遞迴時間複雜度跟迭代一樣,但是空間複雜度為o(n)。

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

限制:

}1 好的資料結構能解決資料的儲存問題,但是不一定能有好的效能。

2 演算法的終極是數學,遇題多思考,多總結。怕什麼真理無窮,進一寸有一寸的歡喜。

經典演算法之約瑟夫環問題

前幾天看到乙個程式設計題,約瑟夫環問題。問題的由來是乙個猶太故事,41乙個人被困,有39個人想要自殺,想活下去的兩個人就出主意說,大家圍成乙個環,報到3的人自殺。結果兩個人成功脫險,也就誕生了這個演算法。由於本人實力有限,寫出的程式也並未進行優化,可能時間複雜度和空間複雜度上有很多問題,只希望給各位...

C 之約瑟夫環

問題原型 在羅馬人占領喬塔帕特後,39 個猶太人與josephus及他的朋友躲到乙個洞中,39個猶太人決定寧願死也不要被敵人抓到,於是決定了乙個自殺方式,41個人排成乙個圓圈,由第1個人開始報數,每報數到第3人該人就必須自殺,然後再由下乙個重新報數,直到所有人都自殺身亡為止。然而josephus 和...

C 之約瑟夫環

0,1,2,3,n 1這n個數排成乙個圈,從數字0開始,每次在圓圈裡面剔除第m個數字。求出這個圓圈最後乙個數字。乙個是使用鍊錶來模擬這個過程 使用公式推導 鍊錶模擬 int lastremaining solution int n,int m else return peoples.begin 公式...