约瑟夫环(约瑟夫问题)是一个数学的应用问题:已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围。从编号为k的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列
前几天笔试的时候遇到过这个问题,求出最后一个出列的数,
想了一个很简单的列表切片方式解决,
在和面试官讲解了思路后,被歧视了。。。。。说是没这么简单,回来后倒腾出来了
基本思路:
假设n=5:list=[1,2,3,4,5]
,m=3:key=m-1
一次循环,以k作为锚点,对list进行切片,切成两个:
list1 = [1,2],list2= [4,5]
然后再合并,形成一个新的list = list2+list1
此时,list = [4,5,1,2]
重复该步骤,当len(list)==1时,弹出list[0]
ok,思路没问题,这部分要注意的是,当nm时,所执行的切片部分略有不同
def ysf(n,m):
list = [x for x in range(1,n+1)]
key = m-1
/如果n或m等于1.直接返回列表的最后一位
if n == 1 or m == 1:
return list[-1]
while True:
/当m<列表长度,直接切片
if m < len(list):
print(list[key])
list = list[key+1:] + list[:key]
print(list)
/当m=列表长度,去掉列表的最后一位
if m == len(list):
list.pop(-1)
print(list)
if m > len(list):
if len(list) == 1:
return list[0]
/当 m>m-len(list),执行循环语句一直减去len(list),直到m小于列表长度
s = m-len(list)
while s > len(list):
s-=len(list)
list = list[s:] + list[:s-1]
print(list)
n,m = 3,10
print(ysf(m,n))
最后执行结果:
3
[4, 5, 6, 7, 8, 9, 10, 1, 2]
6
[7, 8, 9, 10, 1, 2, 4, 5]
9
[10, 1, 2, 4, 5, 7, 8]
2
[4, 5, 7, 8, 10, 1]
7
[8, 10, 1, 4, 5]
1
[4, 5, 8, 10]
8
[10, 4, 5]
[10, 4]
[4]
4
总的来讲。。。这好像是用到了归并的思路?