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