孩子们的游戏(约瑟夫环问题)

孩子们的游戏

题目描述

每年六一儿童节,牛客都会准备一些小礼物和小游戏去看望孤儿院的孩子们。其中,有个游戏是这样的:首先,让 n 个小朋友们围成一个大圈,小朋友们的编号是0~n-1。然后,随机指定一个数 m ,让编号为0的小朋友开始报数。每次喊到 m-1 的那个小朋友要出列唱首歌,然后可以在礼品箱中任意的挑选礼物,并且不再回到圈中,从他的下一个小朋友开始,继续0… m-1报数…这样下去…直到剩下最后一个小朋友,可以不用表演,并且拿到牛客礼品,请你试着想下,哪个小朋友会得到这份礼品呢?
在这里插入图片描述

  1. 暴力模拟
    可以使用环形队列,模拟题目要求,每当到m - 1个个孩子的时候就从队列中删除,依次循环,直到剩下一个孩子。
    使用数组模拟,但是需要注意取模操作,本质也是模拟环形队列,暴力代码不太好写,所以比较推荐第二种方法,也就本篇博客主讲的方法,动态规划。

  2. 动态规划

状态表示是到那个有i个孩子围成一圈的时候,最后剩下的那个孩子的编号是什么。
所以现在假设有i个孩子维成一圈。
在这里插入图片描述
动态规划本质就是寻找dp[i]和dp[i - 1] 的关系,所以我们先找到m-1的孩子把它移除。
在这里插入图片描述
现在假设m-1就落在了4这个位置,那么我们可以把5这个孩子当做0下标,然后它的结果就存在dp[i - 1]中。

在这里插入图片描述

但是5并不是0下标,所以我们需要将m下标与0下标进行一个映射也就是,假设当前的下标是pos, 也就是需要从红色的下标对应到黑色的下标处。那么对应关系就是pos +m。但是对于i - 1下标来说,如果+m就越界了,所以需要对当前的孩子个数取个%,这样就能保证不越界。

class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param n int整型 
     * @param m int整型 
     * @return int整型
     */
    int LastRemaining_Solution(int n, int m) 
    {
        // write code here
        int res = 0;
        for(int i = 1; i <= n; ++i)
        {
            res = (res + m) % i;
        }
        return res;

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

不是笨小孩i

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

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

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

打赏作者

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

抵扣说明:

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

余额充值