有n个人围成一圈,顺序排号,从第一个人开始报数,(从一报到三)凡报到3的人退出圈子,问最后留下来的是原来的第几号
时间: 2023-12-15 11:56:15 浏览: 118
Python使用列表完成程序的编写:有n个人围成一圈,顺序排号。从第一个人开始报数(从1到m报数),凡是报到m的人退出圈子,问最后留下的是原来第几号的人。
5星 · 资源好评率100%
这是经典的约瑟夫问题,可以使用数学归纳法或者循环链表来解决。
方法一:数学归纳法
假设有 $n$ 个人,最后留下来的人的序号为 $f(n)$。我们可以通过已知的 $f(n-1)$ 推导出 $f(n)$。
当 $n=1$ 时,只有一个人,他就是最后留下来的,所以 $f(1)=1$。
当有 $n$ 个人时,第一个出圈的人的编号为 $3\mod n$。假设从编号为 $3\mod n+1$ 的人开始重新编号,那么序号为 $1$ 的人实际上是编号为 $3\mod n+1$ 的人,而序号为 $2$ 的人实际上是编号为 $3\mod n+2$ 的人。因此,当 $n$ 个人时,最后留下来的人的序号为:
$$
f(n)=(f(n-1)+3)\mod n
$$
方法二:循环链表
我们可以用循环链表来模拟这个过程。首先,我们创建一个有 $n$ 个节点的循环链表,每个节点表示一个人,并且节点编号从 $0$ 到 $n-1$。然后,我们从第 $0$ 个节点开始,数数并删除第 $3$ 个节点。重复此过程,直到只剩下一个节点为止,这个节点就是最后留下来的人。
下面是 Python 代码实现:
```python
def josephus(n):
# 初始化循环链表
circle = [i for i in range(n)]
# 从第 0 个节点开始
curr = 0
# 数到第 3 个节点,并删除
while len(circle) > 1:
curr = (curr + 2) % len(circle)
circle.pop(curr)
# 返回最后留下来的节点编号
return circle[0] + 1
```
注意,在 Python 中,列表的索引从 $0$ 开始,所以最后留下来的节点编号需要加 $1$。
阅读全文