约瑟夫问题:
人们站在一个等待被处决的圈子里。 计数从圆圈中的指定点开始,并沿指定方向围绕圆圈进行。 在跳过指定数量的人之后,执行下一个人。 对剩下的人重复该过程,从下一个人开始,朝同一方向跳过相同数量的人,直到只剩下一个人,并被释放。
问题即,给定人数、起点、方向和要跳过的数字,选择初始圆圈中的位置以避免被处决。
历史:
Josephus有过的故事:39 个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被敌人抓。于是决定了自杀方式,41个人排成一个圆圈,由第1个人开始报数,每报数到第3人该人就必须自杀。然后下一个重新报数,直到所有人都自杀身亡为止。然而Josephus 和他的朋友并不想遵从,Josephus要他的朋友先假装遵从,他将朋友与自己安排在第16个与第31个位置,于是逃过了这场死亡游戏。
解法:
比较简单的做法是用循环单链表模拟整个过程,时间复杂度是O(n*m)。n为总人数,m为报到的数。
class Node(object):
def __init__(self, value):
self.value = value
self.next = None
def generate_circle_linkedlist(n):
head = Node(1)
pre = head
for i in range(2, n+1):
new_node = Node(i)
pre.next = new_node
pre = new_node
pre.next = head
return head
def main():
n = 41
m = 3
if m == 1: #特殊情况
print(n)
else:
head = generate_circle_linkedlist(n)
pre = None
cur = head
while cur.next != cur: #循环终止的条件是只剩下一个人
for i in range(m-1):
pre = cur
cur = cur.next
print(cur.value)
pre.next = cur.next
cur.next = None
cur = pre.next
print(cur.value)
if (__name__=="__main__"):
main()
运行结果:
3
6
9
12
15
18
21
24
27
30
33
36
39
1
5
10
14
19
23
28
32
37
41
7
13
20
26
34
40
8
17
29
38
11
25
2
22
4
35
16
31
最后剩下的两个人是16号和31号。