您试图在索引2
删除的项目,但你已经删除了该项目。
Python的索引从0 开始,不为1,所以2
是第三项。换句话说,列表[1, 2]
具有的长度长于1(有2项),但是只有索引0
和1
在该列表中存在。
你可以添加打印到你的循环,看看发生了什么:
def josephus(items, k):
while len(items) > 1:
print(items)
del items[k]
return items
和调用函数与略短名单,以保持输出管理:
>>> josephus([1,2,3,4], 2)
[1, 2, 3, 4]
[1, 2, 4]
[1, 2]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 4, in josephus
IndexError: list assignment index out of range
这说明你是每次删除第三个项目,并且只剩下两个项目时抛出错误。
代替硬编码的长度,你可以测试一个长度超过k
更大:
def josephus(items, k):
while len(items) > k:
del items[k]
return items
现在循环条件,保证有索引k
元素删除:
>>> def josephus(items, k):
... while len(items) > k:
... del items[k]
... return items
...
>>> josephus([1,2,3,4], 2)
[1, 2]
这然而,要删除给定索引之后的所有内容,还有很多工作要做。只需使用一个片:
def josephus(items, k):
del items[k:]
return items
的[k:]
符号告诉Python来解决所有项目开始于索引k
直到列表的末尾(也就是:
后无数值)。
不过,如果你都应该删除每个k
个元素(所以每2或3等),然后你会了解它的错误的方式。再次使用切片表示法:
del items[::k]
我填写片的插槽方面,步幅。这将删除元素0 + 0 * k
,并且0 + 1 * k
和0 + 2 * k
等:
>>> items = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> items[::2]
[1, 3, 5, 7, 9]
>>> del items[::2]
>>> items
[2, 4, 6, 8, 10]
如果你想实现Josephus problem你不能用它来删除的项目,如删除必须是圆形,至少在没有计算下一轮抵消的新起点。使用%
模运算去绕了一圈,调整变化长度:
def josephus(items, k):
skip = k - 1 # deletion removes the item, so skip k - 1
index = skip % len(items)
while len(items) > 1:
del items[index]
index = (index + skip) % len(items)
return items[0]
请注意,我现在返回一个幸存的项目,不在名单。
该代码保持跟踪下一个项目在index
删除。我们从k - 1
开始调整基于0的索引;第二项是在1
。然后,我们围绕“圈子”,通过递增k - 1
的步骤,因为我们刚刚删除了k
这个项目,并且之后的所有内容都会向上移动一圈,并使用%
来回卷到列表的开头。
你在期待这个代码做:
在函数的包装呢? k的意义是什么?由于这种代码的工作方式,除非k为0,否则列表的长度永远不会为0,所以while循环会一直持续,直到您遇到该错误。 – SuperBiasedMan