約瑟夫問題

2021-10-23 03:29:01 字數 2457 閱讀 3270

約瑟夫問題,也叫約瑟夫環。

問題描述:n(編號從0到n-1)個人圍成乙個圈,從0號人開始數(從1開始數),數到第m個人,這個人淘汰。又從下乙個人開始,從1開始數,一直迴圈淘汰到只剩一人,這個人勝出。求這個人的編號。

解法一:模擬

這個問題很多人第一眼看到就覺得不是很簡單嗎,直接模擬就行啊。的確是,用一些列表型別的資料結構模擬一下就很容易做出來了。做法也因人而異。不過這方法只適用於人數和步數很小的時候,數量級一大就沒辦法了。模擬嘛,就是每m步去掉乙個,一共要去掉n-1個,所以時間複雜度是o(nm)。這裡我的方法不用傻乎乎的非要一步步的走,直接m步走,取餘,就能得到要刪除元素的下標。但是消耗時間還是沒解法二快,也許是列表刪除元素需要花費挺多時間,時間複雜度是o(n^2)。就算換成鍊錶,也是耗時間,因為需要找對應下標才能刪除,鍊錶找下標也要很久。python**如下。

# 模擬法

defjosephus1

(n:int

, m:

int)

->

int:

l =list

(range

(n))

idx =

0for i in

range

(n -1)

: idx =

(idx + m -1)

%len

(l) l.pop(idx)

return l[

0]

解法二:公式法其實約瑟夫問題是有規律的。

乙個人數為n,步數為m的約瑟夫環(定義為c(n, m)),走了m步去掉這個人(編號為m % n - 1)之後,又從下乙個人(編號為m)起,重新從0開始編號,這樣就變成了另乙個約瑟夫環c(n-1, m)。

然後一直走m步去掉乙個,約瑟夫環就變成c(n-2, m),c(n-3, m)…c(1, m)。所以求c(n, m),就變成了求c(n-1, m)…求c(1, m),求乙個任務就等於求它的子任務。在這些不斷的縮小的約瑟夫環中,都存在乙個同樣的人,就是倖存者,該編號在不同的約瑟夫環中是不同的。

還有乙個規律,乙個約瑟夫環元素編號可以被下一級約瑟夫環元素編號推出來。比如上圖,我們把這一級的下標和下一級的下標進行對比。

3 — 0

4 — 1

5 — 2

…n-2 — n-5

n-1 — n-4

n — n-3

0 — n-2

1 — n-1

可以發現,兩個下標之間差了m=3步。子任務只要加上m(往左走)就等於原任務的下標了,嚴謹點還得取模。設原任務的下標為idx,子任務的下標為idx』,原任務的人數為n,則公式為:idx = ((idx』 + m) % n)

通過這個公式就可以用子任務的下標推算出上一級任務的下標。而約瑟夫環c(1, m)中的倖存者明顯就是0,這個倖存者是一直存在於上級的每個子任務中的,編號也不同。所以通過這個公式就可以一直推到c(n, m)中倖存者的標號。

比如求c(10, 3)

c(1, 3) = 0

c(2, 3) = (c(1, 3) + 3) % 2 = 1

c(3, 3) = (c(2, 3) + 3) % 3 = 1

…c(10, 3) = (c(9, 3) + 3) % 3 = 3

python**如下:

# 公式法

defjosephus2

(n:int

, m:

int)

->

int:

idx =

0for i in

range(1

, n +1)

: idx =

(idx + m)

% i return idx

m =3

for i in

range(1

,11):

print

('c({}, {}) = {}'

.format

(i, m, josephus2(i, m)))

# c(1, 3) = 0

# c(2, 3) = 1

# c(3, 3) = 1

# c(4, 3) = 0

# c(5, 3) = 3

# c(6, 3) = 0

# c(7, 3) = 3

# c(8, 3) = 6

# c(9, 3) = 0

# c(10, 3) = 3

模擬圖如下:

約瑟夫問題 約瑟夫環

約瑟夫 問題 有時也稱為約瑟夫斯置換,是乙個出現在電腦科學和數學中的問題。在計算機程式設計的演算法中,類似問題又稱為約瑟夫環。又稱 丟手絹問題 據說著名猶太歷史學家 josephus有過以下的故事 在羅馬人占領喬塔帕特後,39 個猶太人與josephus及他的朋友躲到乙個洞中,39個猶太人決定寧願死...

約瑟夫問題 約瑟夫環

約瑟夫問題 有時也稱為約瑟夫斯置換,是乙個出現在電腦科學和數學中的問題。在計算機程式設計的演算法中,類似問題又稱為約瑟夫環。又稱 丟手絹問題 據說著名猶太歷史學家 josephus有過以下的故事 在羅馬人占領喬塔帕特後,39 個猶太人與josephus及他的朋友躲到乙個洞中,39個猶太人決定寧願死也...

約瑟夫問題

這是17世紀的法國數學家加斯帕在 數目的遊戲問題 中講的乙個故事 15個教徒和15 個非教徒在深海上遇險,必須將一半的人投入海中,其餘的人才能倖免於難,於是想了乙個辦法 30個人圍成一圓圈,從第乙個人開始依次報數,每數到第九個人就將他扔入大海,如此迴圈進行直到僅餘15個人為止。問怎樣排法,才能使每次...