問題描述
N個人圍成一個圈, 從第一個人開始報數, 報到M的人出圈, 剩下的人繼續從1開始報數, 報到M的人出圈;如此往復, 直到所有人出圈.
列表解決
def solution_list(n, m):
"""
初始化一個長度為n的列表, 默認值為True. 當某個元素出圈時, 將其置為False.
循環迭代這個列表, 遇到值為False的元素則跳過, 當列表中全為False時表示所有人
都已出圈.
"""
# 初始化列表
people = []
for _ in range(n):
people.append(True)
result = []
num = 1
while any(people):
for index, p in enumerate(people):
if p:
if num == m: # 出圈操作
people[index] = False
result.append(index + 1)
num = 1
else:
num += 1
print('-' * 25)
print(f'\n總人數為{n}, 報數為{m}')
print(f'約瑟夫序列為:\n {result}\n')
print('-' * 25)
def solution_list2(n, m):
"""
這是上面這種思路的另一種解法, 將圈內和圈外表示成0和1.
這里實現循環迭代的方式我第一次遇到, 記錄一下
"""
people = [0 for _ in range(n)]
alive = n # 剩余人數
index = 0
num = 0 # 計數器, 當index == m時出圈
result = []
while alive > 0:
num += 1 - people[index] # 每輪到一個人報數, 不論0或1都進行計數
if num == m:
result.append(index + 1) # 出圈
people[index] = 1 # 將出圈人置為 1
alive -= 1 # 剩余人數 - 1
num = 0 # 重置計數器
# 與總人數 n 取余, 可以實現index在 0 ~ count -1之間一直循環, 達到循環迭代的目的
index = (index + 1) % n
print('-' * 25)
print(f'\n總人數為{n}, 報數為{m}')
print(f'約瑟夫序列為:\n {result}\n')
print('-' * 25)
循環鏈表解決
class Node:
"""節點"""
def __init__(self, value):
self.data = value
self.next = None
def __repr__(self):
return f'Node: {self.data}'
class CircularLinkedList:
"""循環鏈表"""
def __init__(self):
self.rear = None # 尾節點
def is_empty(self):
return self.rear is None
def append(self, elem):
"""尾插法"""
temp = Node(elem)
if self.rear is None:
temp.next = temp
self.rear = temp
else:
temp.next = self.rear.next
self.rear.next = temp
self.rear = temp
def solution_circular_linked_list(n, m):
"""
通過循環鏈表解決, 每次出圈彈出該節點
"""
clist = CircularLinkedList()
for i in range(n):
clist.append(i + 1)
result = []
pre = clist.rear # 當前節點的上一個節點
cur = clist.rear.next # 當前節點
num = 0 # 計數器
while cur.next is not cur:
num += 1
if num == m: # 出圈
result.append(cur.data)
pre.next = cur.next # 彈出當前節點
num = 0 # 重置計數器
else:
pre = pre.next
cur = cur.next
result.append(cur.data)
print('-' * 25)
print(f'\n總人數為{n}, 報數為{m}')
print(f'約瑟夫序列為:\n {result}\n')
print('-' * 25)