约瑟夫环问题
当前有n个人,给定一个数字k,n个人依次从1开始排序,排到k时,当前这个人出列,然后从下一个人开始从1开始继续排序,循环最后出列的人的序号是多少?衍生出的问题是第m轮出列的人的序号是多少?
例子:当前有10个人,给定数字4,进行分析如下,编号从0开始,
0 | 1 | 2 | (3) | 4 | 5 | 6 | 7 | 8 | 9 | 第一轮出列的为3号 |
6 | 7 | 8 | 0 | 1 | 2 | (3) | 4 | 5 | 第二轮出列的是当前序号的3号,原始序列的7号 | |
2 | (3) | 4 | 5 | 6 | 7 | 0 | 1 | 第三轮出列的是当前序号的3号,前一序列的7号,原始序列的1号 |
现在可以进行推导,3=(10+4-1)%10, 3=(9+4-1)%9, 3=(8+4-1)%8
当前序列出列的编号=(当前序列总人数+给定数字-1)%当前序列总人数
当前出列的人在前一序列的编号为:第二次出列的在第一序列的编号:(3+4)%10=7, 第三次出列的在第二次序列的编号:(3+4)%9=7
公式为:(当前序列出列编号+给定数字)%前一序列总数=前一序列编号
继续推导第三次出列的人在原始序列中的编号:已经得到在第二次编号为7,继续套用上面得到的公式(7+4)%10=1,可以得出在原始序列编号为1
综上可以得出,第n次出列的元素,在原始序列的编号,可以通过,求得n-1次的序号,n-2次序号,……,原始序列中的序号。
递归实现
# nums为序列元素个数,values为给定数字,m为轮数
def ysf(nums, values, m):
if m == 1:
return (nums+values-1)%nums
else:
return (ysf(nums-1, values, m-1)+values)%nums
双向链表实现
class Node:
# 构建双向链表节点
def __init__(self, data):
self.data = data
self.pre = None
self.next = None
def ysf_lianbiao(data, values, m):
# 循环轮数
for i in range(m):
# 循环找到出列的元素
for j in range(values-1):
if j != values-2:
data = data.next
else:
# 当前元素的下一个元素为出列元素,删除该元素,如果为最后一轮则返回结果
if i == m-1:
return data.data
tmp = data.next
data.next = tmp.next
tmp.next.pre = data
if __name__ == '__main__':
# 构建双向链表
index = Node(-1)
data = Node(0)
index.next = data
for i in range(1,10):
tmp = Node(i)
data.next = tmp
tmp.pre = data
data = data.next
data.next = index.next
index.next.pre = data
res = ysf_lianbiao(index.next, 4, 10)
print(res)