约瑟夫环2

问题描述:

有n个人站成一列。并从头到尾给他们编号,第一个人编号为1。然后从头开始报数,第一轮依次报1,2,1,2...然后报到2的人出局。接着第二轮再从上一轮最后一个报数的人开始依次报1,2,3,1,2,3...报到2,3的人出局。以此类推直到剩下以后一个人。现在需要求的即是这个人的编号

1 2 1 2 …1 2 31 2 3 ….1 2 3 4 1 2 3 4….1 2 3 4 5 1 2 3 4 5 …..知道最后只剩下一个元素】


 举个例子:假设n = 24,第一个人编号为1。
(1)第一轮:依次报1,2,1,2...然后报到2的人出局,则第一轮过后未出局的编号为1、3、5、7、9、11、13、15、17、19、21、23;
(2)第二轮:从上一轮最后一个报数的人开始依次报1,2,3,1,2,3...报到2,3的人出局。我这里做的处理是,先将上一轮最后一个报数的编号移动到最前面,即23、1、3、5、7、9、11、13、15、17、19、21;然后开始第二轮报数,未出局的编号为23、5、11、17;
(3)第三轮:从上一轮最后一个报数的人开始依次报1,2,3,4,1,2,3,4...报到2,3,4的人出局。同样,我这里做的处理是,先将上一轮最后一个报数的编号移动到最前面,即17、23、5、11;然后开始第三轮报数,未出局的编号为17,此时链表中仅剩一个节点,故程序结束。

解题思路:

将编号 1 - n放入到列表中,当列表中的元素个数大于1的时候进行循环:第二轮循环:【每一轮循环表示一次报数过程】设置变量round并计算当前编号的所报的数字【(cur+1)%roud】,进行判断:如果所报的数字是1,则继续下一个数字;如果所报的数字不是1,则执行列表的删除操作。执行完一轮报数的过程后,需要将左后一个数字移动到列表的第一个位置(题意:从上次报数的最后一个开始报编号1)【利用列表中的 pop()方法:默认删除最后一个元素,并返回最后一个元素的值 】,最后跳出循环并返回列表中唯一一个元素

# -*- coding:utf-8 -*-
class Joseph:
    def getResult(self, n):
        # write code here
        if n < 0:
            return -1
        list1 = []
        i , cur = 0,0
        roud = 2
        for i in range(1,n+1):# 将编号加入到列表中
            list1.append(i)
        while len(list1) > 1:
            i = 0
            while len(list1) > 1 and i < len(list1):
                cur = (cur + 1)%roud # 计算出当前所报的数字
                if cur == 1:# 判断如果数字为1,不进行处理
                    i += 1
                else: # 如果数字不是1,进行删除操作
                    list1.remove(list1[i])
            roud += 1
            cur = 0
            if len(list1) > 1:
                list1.insert(0,list1.pop())# 将最后一个元素删除并插入到首位
        return list1.pop()

阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页