约瑟夫环类似模型:已知有n个人,每次间隔k个人剔除一个,求最后一个剩余的。
此解法为变种,k最初为k-2,之后每次都加1。
例:n=5,k=3。从1开始,第一次间隔k-2=1,将3剔除,第二次间隔k-1=2,将1剔除。依此类推,直至剩余最后一个元素。
核心思路:将原列表复制多份横向展开,同时将间隔存为一个列表。每次根据间隔获取被剔除的元素,同时将此元素存入一个剔除列表中。若被剔除元素不存在于剔除列表,则将其加入,若已存在,则顺势后移至从未加入剔除列表的元素,并将其加入。如此重复n-1次。面试遇到的题,当时只写了思路,没完成代码
#! /usr/bin/env python3 # coding = utf-8 def one_left(n, k): list0 = [i for i in range(1, n + 1)] # 初始列表 listx = [] i = 0 while i <= 2*n: i += 1 listx += list0 # 根据循环次数得到扩大列表 print("listx", listx) list1 = [] # 用于保存被筛掉的元素 intervals = [l for l in range(k - 2, k - 2 + n - 1)] print('intervals', intervals) current_key = 0 # 当前下标 for interval in intervals: # 最外层循环,循环次数为n-1 current_key += (interval + 1) # 间隔数+1 if listx[current_key] not in list1: # 如果剔除元素不在list1中 list1.append(listx[current_key]) else: while True: if listx[current_key] in list1: current_key += 1 else: break list1.append(listx[current_key]) print('剔除列表为:',list1) print('剩余元素为:',set(list0)-set(list1)) def main(): one_left(n=5, k=4) if __name__ == '__main__': main()