1 问题
每年六一儿童节,牛客都会准备一些小礼物和小游戏去看望孤儿院的孩子们。其中,有个游戏是这样的:首先,让 n 个小朋友们围成一个大圈,小朋友们的编号是0~n-1。然后,随机指定一个数 m ,让编号为0的小朋友开始报数。每次喊到 m-1 的那个小朋友要出列唱首歌,然后可以在礼品箱中任意的挑选礼物,并且不再回到圈中,从他的下一个小朋友开始,继续0… m-1报数…这样下去…直到剩下最后一个小朋友,可以不用表演,并且拿到牛客礼品,请你试着想下,哪个小朋友会得到这份礼品呢?
数据范围:1≤n≤5000,1≤m≤10000
要求:空间复杂度 O(1),时间复杂度
示例1
输入:5,3
返回值:3
示例2
输入:2,3
返回值:1
说明:有2个小朋友编号为0,1,第一次报数报到3的是0号小朋友,0号小朋友出圈,1号小朋友得到礼物
示例3
输入:10,17
返回值:2
2 答案
自己写的,循环
class Solution:
def LastRemaining_Solution(self , n: int, m: int) -> int:
res = [i for i in range(n)]
m = m-1
p = 0
while len(res) > 1:
p = (p+m) % len(res)
res.pop(p)
return res[0]
- 递归
n个数相后去掉第m个数,还剩下n−1个数,依然要继续去掉第m个数。由此,从(n,m)的问题变成了(n−1,m)的子问题,其中若是(n−1,m)的子问题返回的最后一个数是x,则(n,m)返回的结果就是(m+x)%n,因此,用递归解决。
- 终止条件: 当n=1时就只剩下了最后一个孩子,应该返回0。
- 返回值: 子问题的结果加上m再对n取模,就是上一级删除的元素。
- 本级任务: 递归进入子问题获取子问题删除的元素,再推算自己这一级删除的元素。
具体做法:
- step 1:首先判断没有小朋友的特殊情况。
- step 2:然后递归计算子问题,并将子问题的结果x运算(m+x)%n得到父问题的结果。
import sys
sys.setrecursionlimit(100000)
class Solution:
def function(self, n: int, m: int) -> int:
if n == 1:
return 0
x = self.function(n-1, m)
return (m + x) % n
def LastRemaining_Solution(self , n: int, m: int) -> int:
if n == 0 or m == 0:
return -1
return self.function(n, m)
- 迭代
方法一的递归也我们可以用迭代来代替,递归是自顶向下找子问题,根据子问题再自顶向上返回给父问题,来推算父问题的结果。我们可以直接从小的子问题,往上推,还是根据公式(m+x)%n,只是这里的n变成了每一级子问题的长度。
- step 1:首先判断没有小朋友的特殊情况。
- step 2:假设最后剩余1个的时候,结果肯定为0.
- step 3:从最后剩余1个小朋友推断2个,再不断根据公式推断到n个。
class Solution:
def LastRemaining_Solution(self , n: int, m: int) -> int:
if n == 0 or m == 0:
return -1
x = 0
for i in range(2, n + 1):
x = (m + x) % i
return x
https://www.nowcoder.com/share/jump/9318638301700374211453