劍指Offer 62 圓圈中最後剩下的數字

2022-03-06 10:42:43 字數 1905 閱讀 5125

劍指offer

contents解答解答2:數學公式法

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 <= n <= 10^5

1 <= m <= 10^6

按照題目意思,模擬題目描述的這個過程,一定可以得到答案,這就是模擬法。必須使用arraylist來模擬"數字組成的圓圈",才可以通過;如果使用linkedlist來模擬,時間超出限制。

演算法流程

把0~n-1的數字新增到arraylist資料結構中。

按照題目規則,模擬刪除節點的過程。

返回最後剩下的乙個數字。

這個問題其實是乙個經典的數學問題,叫做"約瑟夫環"問題,可以通過乙個遞推關係式來計算倖存者的位置。數學公式法特點是公式推導過程比較難理解,但是一旦推導出公式,編碼變得非常簡單,且**執行效率很高。

以下引用了一張題解中的圖,這張清晰地展示了遞推過程。

以上描述的過程是從上到下的過程,從原陣列裡逐漸刪除數字,最後僅剩乙個倖存數字。

那麼重點來了,我們如果從下往上看,可以發現乙個倒推的規律,與上述規律是互逆的。

從上向下看,倖存數字3每次向前移動m位;從下往上看,規律就是,倖存數字3每次向後移動m位。

並且,我們還有乙個條件,倖存數字最後的索引一定是0

根據這兩個條件,我們可以發現從下往上看,倖存數字的索引的變化規律。

(當前index + m) % 上一輪剩餘數字的個數

遞推公式如下:

最後,我們找到了倖存數字在原陣列裡邊的索引是3,由於原陣列是0~n-1有序陣列,索引就等於索引位置上的元素,直接返回3。

總結一下,首先我們按照題目規則,一步步推導,可以得到最後倖存的數字3。得到倖存數字之後,從下到上觀察倖存數字索引的變化,我們可以發現乙個倒推的規律,利用這個規律,可以計算出倖存數字在原陣列裡的索引。

class

solution

int idx = 0;

//按照規則,模擬刪除節點的過程

while(n > 1)

//返回最後剩下的數字

return list.get(0);}}

複雜度分析

時間複雜度:大概是o(n2),因為remove()的複雜度是o(n)

空間複雜度:o(n),借助乙個arraylist

class

solution

return ans;}}

複雜度分析

時間複雜度:o(n)

空間複雜度:o(1)

劍指 Offer 62 圓圈中最後剩下的數字

題目 題目描述 0,1,n 1這n個數字排成乙個圓圈,從數字0開始,每次從這個圓圈裡刪除第m個數字。求出這個圓圈裡剩下的最後乙個數字。例如,0 1 2 3 4這5個數字組成乙個圓圈,從數字0開始每次刪除第3個數字,則刪除的前4個數字依次是2 0 4 1,因此最後剩下的數字是3。示例 1 輸入 n 5...

劍指 Offer 62 圓圈中最後剩下的數字

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 輸出 ...

劍指 Offer 62 圓圈中最後剩下的數字

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 輸出 ...