【剑指offer】JZ62 孩子们的游戏(圆圈中最后剩下的数)

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]

在这里插入图片描述

  1. 递归

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)
  1. 迭代

方法一的递归也我们可以用迭代来代替,递归是自顶向下找子问题,根据子问题再自顶向上返回给父问题,来推算父问题的结果。我们可以直接从小的子问题,往上推,还是根据公式(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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LouHerGetUp

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值