算法学习笔记:约瑟夫问题

约瑟夫问题

据说著名犹太历史学家 Josephus有过以下的故事:

在罗马人占领乔塔帕特后,39 个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被敌人抓到,于是决定了一个自杀方式,41个人排成一个圆圈,由第1个人开始报数,每报数到第3人该人就必须自杀,然后再由下一个重新报数,直到所有人都自杀身亡为止。

然而Josephus 和他的朋友并不想死,那么约瑟夫及其朋友应该怎样安排自己得位置才能逃过一劫?

算法

  1. 有n个人围成一圈,顺序排号。
  2. 从第一个人开始报数(从1到3报数),凡报到3的人退出圈子,重新计数。
  3. 循环直到剩下最后N个人

代码

n = int(input("输入N: "))  # 输入总人数

ll = [i + 1 for i in range(n)]  # 生成队列

print(ll)
suvivor = 2  # 设定最后得幸存者

i = 0
l = len(ll)
k = 1  # 报数

while l > suvivor:
    if i == len(ll):  # 报数结束,从第一个人重新开始报数
        i = 0
    if k == 3:  		# 0. 报数到 3:
        print("kill : ", ll[i])
        ll.pop(i)       # 1. 移除这个人
        l = len(ll)     # 2. 新的队列长度
        k = 1           # 3. 报数回归到1
        i -= 1          # 4. 因为删掉一个人,所以当前坐标 -1,否则后面坐标加上以后,就会出错。
    else:
        k += 1
    i += 1

print(ll)

结果

输入N: 41
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41]
kill :  3
kill :  6
kill :  9
kill :  12
kill :  15
kill :  18
kill :  21
kill :  24
kill :  27
kill :  30
kill :  33
kill :  36
kill :  39
kill :  1
kill :  5
kill :  10
kill :  14
kill :  19
kill :  23
kill :  28
kill :  32
kill :  37
kill :  41
kill :  7
kill :  13
kill :  20
kill :  26
kill :  34
kill :  40
kill :  8
kill :  17
kill :  29
kill :  38
kill :  11
kill :  25
kill :  2
kill :  22
kill :  4
kill :  35
[16, 31]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值