力扣面試題62 圓圈中最後剩下的數字

2021-10-04 13:54:47 字數 1348 閱讀 2877

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

約塞夫問題:

下面這個例子是n=8 m=3的例子

我們定義f(n,m)表示最後剩下那個人的索引號,因此我們只關係最後剩下來這個人的索引號的變化情況即可

從8個人開始,每次殺掉乙個人,去掉被殺的人,然後把殺掉那個人之後的第乙個人作為開頭重新編號

第一次c被殺掉,人數變成7,d作為開頭,(最終活下來的g的編號從6變成3)

第二次f被殺掉,人數變成6,g作為開頭,(最終活下來的g的編號從3變成0)

第三次a被殺掉,人數變成5,b作為開頭,(最終活下來的g的編號從0變成3)

以此類推,當只剩乙個人時,他的編號必定為0!(重點!)

3 最終活著的人編號的反推

現在我們知道了g的索引號的變化過程,那麼我們反推一下

從n = 7 到n = 8 的過程

如何才能將n = 7 的排列變回到n = 8 呢?

我們先把被殺掉的c補充回來,然後右移m個人,發現溢位了,再把溢位的補充在最前面

神奇了 經過這個操作就恢復了n = 8 的排列了!

因此我們可以推出遞推公式f(8,3)=[f(7,3)+3]%8

進行推廣泛化,即f(n,m)=[f(n−1,m)+m]%n

4 遞推公式的匯出

再把n=1這個最初的情況加上,就得到遞推公式

f(n,m)=0,n=1

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

class solution(object):

def lastremaining(self, n, m):

""":type n: int

:type m: int

:rtype: int

"""p = 0

for i in range(2, n + 1):

p = (p + m) % i

return p

面試題62 圓圈中最後剩下的數字

面試題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...

面試題62 圓圈中最後剩下的數字

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

面試題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 ...