问题描述
约瑟夫环问题可描述为:几个人(以编号1,2,3,…,n分别表示)围坐在一张圆桌周围。从编号为k的人从1开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,每一次都有人出列,直至最后一人胜利。
算法分析
我们可以对n个人编号0~(n−1),从0开始报数,报到(m−1)的人退出,剩下的人继续从1开始报数,求胜利者的编号。假如知道这个子问题的解:例如x是最终的胜利者,那么把x变回去刚好就是n个人情况,变回去的公式可表述为x’=(x+k)%n。想知道(n−1)个人报数问题的解,只要知道(n−2)个人报数问题的解即可。假设用f表示第i个人玩游戏,报出m退出以后最后胜利者的编号(报数),最后的结果自然是f [n]。递推公式可表述为:f[1]=0;f=(f[i-1]+m)%i (i>1);
Python求解实现
# 定义结点类型
class Node():
def __init__(self, value, next=None):
self.value = value
self.next = next
def creatLink(n):
if n <= 0:
return False
if n == 1:
return Node(1)
else:
root = Node(1)
temp = root
for i in range(2, n+1):
temp.next = Node(i)
temp = temp.next
temp.next = root
return root
def showLink(root):
temp = root
while True:
print(temp.value)
temp = temp.next
if temp == None or temp == root:
break
def josephus(n,k):
if k == 1:
print('remain:', n)
return
root = creatLink(n)
temp = root
while True:
for i in range(k-2):
temp = temp.next
print('Kill:', temp.next.value)
temp.next = temp.next.next
temp = temp.next
if temp.next == temp:
break
print('Winner:', temp.value)
if __name__ == '__main__':
josephus(10, 4)