【题目】每年六一儿童节,牛客都会准备一些小礼物去看望孤儿院的小朋友,今年亦是如此。HF作为牛客的资深元老,自然也准备了一些小游戏。其中,有个游戏是这样的:首先,让小朋友们围成一个大圈。然后,他随机指定一个数m,让编号为0的小朋友开始报数。每次喊到m-1的那个小朋友要出列唱首歌,然后可以在礼品箱中任意的挑选礼物,并且不再回到圈中,从他的下一个小朋友开始,继续0...m-1报数....这样下去....直到剩下最后一个小朋友,可以不用表演,并且拿到牛客名贵的“名侦探柯南”典藏版(名额有限哦!!_)。请你试着想下,哪个小朋友会得到这份礼品呢?(注:小朋友的编号是从0到n-1)
【思路】每次删除的数的小标为(m-1)%len(num),删除一个后,则后面的节点变成了头节点
【代码】
class Solution:
def LastRemaining_Solution(self, n, m):
# write code here
if n<=0:
return -1#判断异常输入
num = list(range(n))
while len(num)>1:
lucky = (m-1)%len(num)
num = num[lucky+1:]+num[:lucky]
return num[0]
【思路2】
首先我们定义一个关于 n 和 m 的方程町矶时,表示每次在 n 个数字 0,1, … ,n-1中每次删除第 m 个数字最后剩下的数字。
在这 n个数字中, 第一个被删除的数字是(m-1)%n。为了简单起见,我们把(m- 1)%n 记为 k,那么删除k之后剩下的 n-1 个数字为 0,1,… ,k-1,k+1,… ,n-1,并且下一次删除从数字 k+1 开始计数。相当于在剩下的序列中, k+1 排在最前面,从而形成 k+1,... ,n- 1,0,I,… ,k-1 。该序列最后剩下的数字也应该是关于 n 和 m 的函数。由于这个序列的规律和前面最初的序列不一样(最初的序列是从 0 开始的连续序列),因此该函数不同于前面的函数,记为 f’(n-1,m)。最初序列最后剩下的数字 f(n, m)一定是删除一个数字之后的序列最后剩下的数字,即 f(n, m)=f’(n-1, m)。
接下来我们把剩下的这 n-1 个数字的序列 k-1, …,n-1,0,1,… ,k-1 做一个映射,映射的结果是形成一个从 0 到 n-2 的序列:
image.png
【代码】
class Solution:
def LastRemaining_Solution(self, n, m):
# write code here
if n<=0:
return -1#判断异常输入
last = 0
for i in range(2,n+1):
last = (last+m)%i
return last
网友评论