環形單鏈表的約瑟夫問題

2021-09-29 12:36:19 字數 4498 閱讀 9855

據說著名猶太歷史學家 josephus有過以下的故事:在羅馬人占領喬塔帕特後,39 個猶太人與josephus及他的朋友躲到乙個洞中,39個猶太人決定寧願死也不要被敵人抓到,於是決定了乙個自殺方式,41個人排成乙個圓圈,由第1個人開始報數,每報數到第3人該人就必須自殺,然後再由下乙個重新報數,直到所有人都自殺身亡為止。

然而josephus 和他的朋友並不想遵從。首先從乙個人開始,越過k-2個人(因為第乙個人已經被越過),並殺掉第k個人。接著,再越過k-1個人,並殺掉第k個人。這個過程沿著圓圈一直進行,直到最終只剩下乙個人留下,這個人就可以繼續活著。

問題是,給定了和,一開始要站在什麼地方才能避免被處決?josephus要他的朋友先假裝遵從,他將朋友與自己安排在第16個與第31個位置,於是逃過了這場死亡遊戲。

稍微改一下書中的題意,只求最後活下來的人

鍊錶節點

class

node()

:def

__init__

(self, val)

: self.val = val

self.

next

=none

問題求解

def

josephus

(head, m)

:if head is

none

or head.

next

== head or m <0:

return head

prev, cur =

none

, head

x =0while cur != prev:

if x == m-1:

prev.

next

= cur.

next

x =0else

: x +=

1next

= cur.

next

prev = cur

cur = cur.

next

return cur.val

測試

def

make_cycle_list

(l):

head, tail =

none

,none

for x in l:

node = node(x)

if tail is

none

: head = node

else

: tail.

next

= node

tail = node

tail.

next

= head

return head

deftest_josephus

(n, m)

: l =

for i in

range

(n):

head = make_cycle_list(l)

x = josephus(head, m)

print

(x)

遞迴求解:

n個人(編號[0, n-1]),從0開始迴圈報數,報到m-1被殺,直到剩下乙個,求最終剩下誰

假如n = 1,則肯定剩下編號為0的人即

f(1, m) = 0

n個人,從0報到m-1,

例如,n=6, m= 4, 6個人,報數到3,則第一次被殺的是3 = m-1 = (m-1) % n

序號:0, 1, 2, 3, 4, 5

報數:0, 1, 2, 3

n = 6, m = 9, 6個人,報數到8,第一次被殺的是 2 = (m-1) % n

序號:0, 1, 2, 3, 4, 5

報數:0, 1, 2, 3, 4, 5

報數:6, 7, 8

所以,無論m < n還是m >= n,第一次被殺的都可以表示為k = (m-1) % n

第二輪,還剩下n-1個人,從4開始報數,

序號:0, 1, 2, 3 ,4, 5

報數:0, 1, 2, 3,0, 1

報數:2, 3

而假設原始問題就是n=5, m= 4

序號:0, 1, 2, 3, 4

報數:0, 1, 2, 3

序號對應關係:

4, 5, 0, 1, 2

0, 1, 2, 3, 4

4 = 0+4

5 = 1+4

0 = (2+4) % 6

1 = (3+4) % 6

2 = (4+4) % 6

4,5後面%6 依然成立。

因此 f(4, 4) = (f(5, 4) + m) % n,

這樣我們把問題縮小到乙個更加簡單的問題,

類似地:

f(n, m) = (f(n-1, m) + m) % n

def

get_josephus_live

(n, m)

:if n ==1:

return

0return

(get_josephus_live(n-

1, m)

+ m)

% n

測試:

def

test_josephus2

(n, m)

: x = get_josephus_live(n, m)

;print

(x)if __name__ ==

'__main__'

:print

('5, 6'

) test_josephus(5,

6)test_josephus2(5,

6)print

('------------------------------'

)print

('6, 3'

) test_josephus(6,

3)test_josephus2(6,

3)print

('------------------------------'

)print

('16, 5'

) test_josephus(16,

5)test_josephus2(16,

5)print

('------------------------------'

)print

('6, 15'

) test_josephus(6,

15)test_josephus2(6,

15)print

('------------------------------'

)print

('500, 123'

) test_josephus(

500,

123)

test_josephus2(

500,

123)

print

('------------------------------'

)print

('500, 1234'

) test_josephus(

500,

1234

) test_josephus2(

500,

1234

)print

('------------------------------'

)

➜  6_josephus python josephus.py5,

633-

----

----

----

----

----

----

----

-6,3

00--

----

----

----

----

----

----

----

16,55

5---

----

----

----

----

----

----

---6

,1533

----

----

----

----

----

----

----

--500,

1237575-

----

----

----

----

----

----

----

-500

,1234

477477--

----

----

----

----

----

----

----

環形單鏈表約瑟夫問題

乙個環形單鏈表,從頭結點開始向後,指標每移動乙個結點,就計數加1,當數到第m個節點時,就把該結點刪除,然後繼續從下乙個節點開始從1計數,迴圈往復,直到環形單鏈表中只剩下了乙個結點,返回該結點。思路 當鍊表為空或者鍊錶只有乙個節點或者m 1時,不做處理,直接返回原鍊錶即可。if head null h...

環形單鏈表的約瑟夫問題

輸入 乙個環形單鏈表的頭結點head和報數的值m。返回 最後生存下來的節點,且這個節點自己組成環形單向鍊錶,其他節點都刪掉。高階 如果鍊錶節點數為n,想在時間複雜度o n 時完成原問題的要求,該如何實現?public class josephuskill1 public node josephusk...

環形單鏈表的約瑟夫問題

題目 約瑟夫環 約瑟夫問題 是乙個數學的應用問題 已知n個人 以編號1,2,3 n分別表示 圍坐在一張圓桌周圍。從編號為k的人開始報數,數到m的那個人出列 他的下乙個人又從1開始報數,數到m的那個人又出列 依此規律重複下去,直到圓桌只剩乙個人。解題思路 1 如果鍊錶為空,或者鍊錶節點數為1,retu...