【问题标题】:What is going wrong inside of my loop?我的循环内部出了什么问题?
【发布时间】:2015-04-29 01:29:36
【问题描述】:

我一直在尝试对Josephus problem 进行编程,但由于某种原因它只能在某些情况下工作,我不确定为什么。其工作原理的 TL;DR 是这样的:

你有 X 组人在一个圈子里。每第 N 个人都会被杀死,直到只剩下最后一个人。例如,假设你有 10[AKA: X] 人,你决定杀死每 3 个 [AKA: Nth] 人,它看起来像这样:

第一轮:1, 2, (3 dies), 4, 5, (6 dies), 7, 8, (9 dies), 10

第二轮:1,(2死,因为它是一个连续的圆圈),3,5,(7死),8,10

第三轮:(1), 4, 5, (8), 10

第四轮:4、(5)、10

第五轮:4,(10)

最后我们只剩下 #4 号作为唯一幸存者了。

我的程序完全可以做到这一点。但是,当我输入 X 为 55 和 N 为 17 时,我得到的人 27 的错误答案应该是人 40。谁能告诉我我的循环哪里出了问题?

源代码:

def solveJosephus(specifics):
    people = [int(x) for x in range(1,int(specifics[0])+1)]
    killPosition = int(specifics[1])
    positionCounter = 0
    sorted = False

    while not sorted:
        if len(people) == 1:
            print(people[0]) # Pyschologically scarred Winner!
            sorted = True
        for person in people:
            positionCounter += 1
            if positionCounter == killPosition:
                print(person)
                people.remove(person)
                positionCounter = 1

solveJosephus(raw_input().split())

【问题讨论】:

  • 应该是people = range(1, int(specifics[0])+1)。 Python 2.x 中内置的 range 函数保证会生成一个整数列表,因此再次将它们映射到整数是多余的。
  • 另外,我相信通过迭代 OrderedSet 的副本并从中删除元素可以达到更好的时间复杂度:code.activestate.com/recipes/576694 或者也许只是使用内置的 Python 集并迭代从集合生成的排序列表,例如for person in sorted(survivors): 也有可能在这里找到递归关系,从而产生有效的动态规划解决方案。最有效的解决方案可能使用数学公式:)

标签: python python-2.7 loops


【解决方案1】:

问题是您在遍历列表时要从列表中删除人员。

会发生以下情况:

假设你有X = 5N = 2。你的名单是[1,2,3,4,5]。你到达index = 1 并且人 2 死了。现在你的名单是[1,3,4,5]。问题是您的索引仍然等于1,但现在它指向第 3 个人。当您再去两个地方(索引 = 3)时,不是杀死第 4 个人,而是杀死第 5 个人。

【讨论】:

    【解决方案2】:

    除了所有otheranswers(告诉您在迭代时制作列表的副本)之外,您的代码的另一个问题是您在此行中将positionCounter重置为1:positionCounter = 1 .它应该重置为 0。这是完整的工作代码(到目前为止工作):

    def solveJosephus(specifics):
        people = [int(x) for x in range(1,int(specifics[0])+1)]
        killPosition = int(specifics[1])
        positionCounter = 0
        sorted = False
    
        while not sorted:
            if len(people) == 1:
                print(people[0]) # Pyschologically scarred Winner!
                sorted = True
            for person in people[:]: #Make copy of iterating list
                positionCounter += 1
                if positionCounter == killPosition:
                    print(person)
                    people.remove(person)
                    positionCounter = 0 #Important! 0 != 1
    
    solveJosephus(raw_input().split())
    

    【讨论】:

      【解决方案3】:

      我不确定为什么您有时会得到正确或错误的答案,但是如果我尝试修改列表同时将其作为您的列表进行迭代,我总是会遇到奇怪的问题

      for person in people:
          ...
          people.remove(person)
      

      确实如此。也许你可以迭代 people.copy() ,这样你就不会修改你正在迭代的同一个列表。

      【讨论】:

        猜你喜欢
        • 2015-01-09
        • 1970-01-01
        • 2020-08-06
        • 1970-01-01
        • 2011-04-26
        • 2014-02-15
        • 1970-01-01
        • 1970-01-01
        • 2011-04-23
        相关资源
        最近更新 更多