问题:
15个人围成圈数数 每逢报数为七的倍数就退出,一直循环下去 ,
直到剩下最后一人 ,最后剩余的是第几个人,展示出退出的顺序。
代码:
PS:如果代码有哪里不理解可以看下面的分析,如果能理解,就不用浪费时间看下面的分析了
peo_num = 15
a = []
for i in range(peo_num):
a.append(i+1)
# 被删除的元素
be_del = []
# 报数
num = 0
# 列表大于一个就循环
while len(a) >1:
# 由于删除 元素后,索引会变,change_index 为索引改变的值
change_index =0
# 循环a列表
for i in range(len(a)):
# 报数
num += 1
# 如果num 为 7 的倍数
if num % 7 == 0:
# 删除元素,并添加到be_del 列表
be_del.append(a.pop(i - change_index))
# 由于删除了一个元素,本次循环的列表的索引就改变了1
change_index += 1
# 删除完元素。清除 change_index
change_index = 0
print('最后剩下的人:',a)
print('退出的顺序::',be_del)
需求:
- 1,求出,最后剩下的那个人
- 2,退出的顺序
思路
首先,我们要15个人列出来,很显然,这应该用集合表示,根据题目,报数为7的倍数的,退出(退出的还要进行排序),这个集合要支持删除元素,我在这里就用两个列表了。
这道题的逻辑很简单,就是吧报数为 7 的倍数的元素的删除,并追加到一个新的列表中。
根据题目,15个人围成一圈,在人数发生改变的时候,但是报数不会重新开始,很显然,一个循环满足不了我们的需求,所以,我要用到两个循环,循环里面嵌套一个循环。外部的循环在人数大于1(即列表的长度大于1)的时候,报数不结束,内部的循环就是每个报数。在内部循环,进行判断,如果这个人的报数为7的倍数,则从列表中去除他,并且追加到一个新列表。
到这里,我们就可以开始代码,根据思路,我们可以写出下面的代码
peo_num = 15
a = []
for i in range(peo_num):
a.append(i+1)
# 报数
num = 0
# 退出的列表
be_del = []
# 列表大于一个就循环
while len(a) >1:
# 循环a列表
for i in range(len(a)):
# 报数
num += 1
# 如果num 为 7 的倍数
if num % 7 == 0:
# 删除元素,并添加到be_del 列表
be_del.append(a.pop(i))
print('最后剩下的人:', a)
print('退出的顺序:', be_del)
运行结果:
...
be_del.append(a.pop(i))
IndexError: pop index out of range
这里说我们删除的时候,索引超出了列表的长度,这里就会有人有疑问,
我们是根据列表的的索引来删除的,怎么会超出范围的。其实,这个问题简单,就是我在此之前删除了一个元素,列表的长度也会对应发生改变,但是在这个循环中 i 还是列表没有发生改变前的索引,当 i 是列表未改变的最大索引,当我们根据 i 去删除 改变后的列表对应的值的时候,就发现列表的长度不够,也就是,索引超出了列表的长度
那么这个问题怎么解决呢?
很简单,列表既然发生了变化,那么我们就把这个变化记下来,等下次列表发生变化的时候,这个变化给 i 。
peo_num = 15
a = []
for i in range(peo_num):
a.append(i+1)
# 被删除的元素
be_del = []
# 报数
num = 0
# 列表大于一个就循环
while len(a) >1:
# 由于删除 元素后,索引会变,change_index 为索引改变的值
change_index =0
# 循环a列表
for i in range(len(a)):
# 报数
num += 1
# 如果num 为 7 的倍数
if num % 7 == 0:
# 删除元素,并添加到be_del 列表
be_del.append(a.pop(i - change_index))
# 由于删除了一个元素,本次循环的列表的索引就改变了1
change_index += 1
# 删除完元素。清除 change_index
change_index = 0
print('最后剩下的人:',a)
print('退出的顺序::',be_del)
结果:
最后剩下的人: [5]
退出的顺序:: [7, 14, 6, 15, 9, 3, 13, 11, 10, 12, 2, 8, 1, 4]