約瑟夫環問題是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 公式...