话很少说,直接上需求,如题。python
''' 有20我的围城一圈(编号0~19),从第0号的人从8开始报数,凡报到3的倍数的人离开圈子,而后再继续数下去,直到最后剩下两人为止,剩余这两人原来的位置是多少号? '''
拿到这个题,咱们先分析下,说是20我的围成一圈,从0开始编号,0号位的人开始从8开始报数,3的倍数的直接出局,报数嘛,就是自增1呗。重点是循环报数,找到最后的两我的,其实剩几我的均可以,原理上都是同样的,只是最后的判断条件改个参数而已。回归正题,既然是循环报数,那么就能够想到递归,重复的调用函数体,这样别说是20个,就算是2000我的也能够找得出来,重点是不能超过python的最大递归深度。函数
这里呢,我把这20我的的位号写进一个列表里。这里须要注意的是不能直接循环原列表来进行判断删除,由于在python里边,删除中间的一个元素的话,后边的会遇上来,这样从删除的第一元素后边的全部的位号都是错误的,这样最终的确定也得不到正确的结果。优化
大概的思路分析就到这里,下来咱们用python代码来实现下。spa
# 生成20我的的座位号 l = [i for i in range(20)] li = l[:] # 将原始的座位号copy一份出来 n = 8 # 报数的起始数 def f(n, li): ''' 递归查找最后的两我的 :param n: 每轮的起始报数值 :param li: 每轮起始的剩余人的座位号列表 :return: 每轮剩余的人的座位号列表 ''' for i in li: # 判断当前报数是否为3的倍数,是的话该人直接出局 if n % 3 == 0: l.remove(i) # 判断列表中还剩多少人,剩余2人终止递归 if len(l) == 2: return l n += 1 # 报数自增1 li = l[:] # 一次递归调用后剩下的人,copy一份数据供下次递归使用 return f(n, li) print(f(n, li))
以上就是py代码的实现,这个代码呢写的也很low,时间复杂度空间复杂度都不最后化,仅供参考使用。很定也会有大佬能写出更优化的代码。code
这道题也算是比较经典了,网上也有不少大佬用其余语言实现了,因为我只精通python,就用py代码实现下,若是有其余什么问题,欢迎各位大佬前来指导交流。blog