约瑟夫环问题 正面肛

见很多大佬都是深知该题的数学规律,然后使用数学方法立项解题的,而我就不一样了,数学菜的一批,根本不知道往哪里找规律,就只能正面刚这道题

题目版本很多,大致意思都差不多,这里使用的是自己理解后的约瑟夫环问题的题目:

  1. 有n个人围成一圈,顺序排号
  2. 从第一个人开始报数(从1到3报数),报到3的人直接弄死,再从他的下一个人开始报数(从1到3报数)
    问:最后留下的是哪位?

我先假设人共有10人,装进一个列表里:

list=[1,2,3,4,5,6,7,8,9,10]

通过纸和笔运算,很快就可以得到,天选之子为4号,有了思路后,开始分析:

第一个死的就是3号,打算使用list.pop()方法杀掉他,但是这个位置上的也不一定是3号,只要处在list[2]位置上的,就得死,所以杀掉报数为3的人的方法就是list.pop(list[2]),此时列表长度就少了一个人,同理,给位置一个参数num,然后让它自加2,杀掉下一个。

但这样下去,索引长度肯定会超过列表自身的长度的,因为每杀一个人,列表自身也在缩短一个单位,num总会大于list的长度的,所以要num-(len(list)-1),因为num是列表的位置,而列表本身与位置索引是相差1的,所以列表自身要减1,再给他们整体减1,才是需要的下一个报数为3的人的列表索引值,即num = (num - (len(list1) - 1)) - 1,理完思路了,就可以写代码了


l1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]


def JosephRing(list1):
    """
    主要方法为列表位置元素的删除、try的捕获IndexError后更新num的位置信息
    :return:
    """
    num = 2
    while True:
        try:
            list1.pop(num)
            num += 2
        except IndexError:
            if len(list1) == 1:
                return l1[0] # 返回列表中的唯一一个值,即天选之子
            else:
                num = (num - (len(list1) - 1)) - 1  # 留意实际要删除的数据的位置
                continue


if __name__ == '__main__':
    print(JosephRing(l1))


# 输出结果

4
>>>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值