zoukankan      html  css  js  c++  java
  • 孩子们的游戏(圆圈中最后剩下的数)

    时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32M,其他语言64M

    题目描述

    每年六一儿童节,牛客都会准备一些小礼物去看望孤儿院的小朋友,今年亦是如此。HF作为牛客的资深元老,自然也准备了一些小游戏。其中,有个游戏是这样的:首先,让小朋友们围成一个大圈。然后,他随机指定一个数m,让编号为0的小朋友开始报数。每次喊到m-1的那个小朋友要出列唱首歌,然后可以在礼品箱中任意的挑选礼物,并且不再回到圈中,从他的下一个小朋友开始,继续0...m-1报数....这样下去....直到剩下最后一个小朋友,可以不用表演,并且拿到牛客名贵的“名侦探柯南”典藏版(名额有限哦!!^_^)。请你试着想下,哪个小朋友会得到这份礼品呢?(注:小朋友的编号是从0到n-1)
    如果没有小朋友,请返回-1

    思路:

    根据题目描述,这就是一个约瑟夫环的问题。

    定义一个关于m 和n的方程,f(n,m),表示n个数字0,1,2,….n-1;
    中每次删除第m个数字最后剩下的数字。
    第一个被删除的数字(m-1)%n.
    例如0,1,2,3,4,5,删除第3个,即2,那么(3-1)%6=0….2,商0余2,所以2就是那个被删除的数。
    在删除第m个数字(定义为k)之后的序列为
    0,1,2,…k-1,k+1,…n-1;
    在进入下一次循环时删除第m个的时候从第k+1个数开始,这个序列为k+1,,,n-1,0,1,…k-1;函数因此定为f(n-1,m)
    再将这个映射我从0开始的序列,如下:
    K+1 → 0;
    K+2 → 1;

    n-1 → n-1-(k+1)=n-k-2;
    0 → n-k-2+1=n-k-1;
    1 → n-k;

    k-1 → n-k-1+(k-1)=n-2;
    映射p(x)=p(x-k-1)%n;表示映射钱的数字是x,映射后的数字是x-k-1。逆映射为
    P
    (x)=(x+k+1)%n.
    这里记住无论循环多少次删除第m个元素最后剩下的数字是一样的。
    f*(n-1,m)=P*( f(n-1,m))=( f(n-1,m)+k+1)%n.=(f(n-1,m)+m)%n.
    因为k=(m-1)%n=(m-1)

    class Solution {
    public:
        int LastRemaining_Solution(int n, int m)
        {
            if(n < 1|| m <1)
                return -1;
            int last = 0;
            for(int i =2;i <= n ;i++)
                last = (last + m)%i;
            return last;
        }
    };
    

    另一种方法采用数组来模拟环的效果,依次寻找第m个数,其中要涉及对要删除元素值的改变,以及注意开始遍历元素下标的处理

    class Solution {
    public:
        int LastRemaining_Solution(int n, int m)
        {
            if(n<1|| m<1)
                return -1;
            int elem[n];
            for(int i = 0;i < n;i++)
                elem[i] = i;
            int i = -1,step = 0,count = n;//i用于记录起始位置,step用于寻找m,count剩下的数目
            
            while(count>0)//跳出循环时将最后一个元素也设置为了-1
            {
                i++;//指向上一个被删除对象的下一个元素
                if(i >= n)//模拟环
                    i = 0;
                if(elem[i] == -1)//跳过被删除的对象
                    continue;
                step++;//记录已走过的
                if(step == m)//找到待删除对象
                {
                    elem[i] = -1;
                    step =0;
                    count--;
                }
            }
            return i;
        }
    };
    
  • 相关阅读:
    Linux 学习 step by step (1)
    ubuntu server nginx 安装与配置
    ubuntu server samba服务器配置
    iOS app集成支付宝支付流程及后台php订单签名处理
    mac 连接windows 共享内容
    linux 文件查找,which,whereis,locate,find
    ubuntu server vsftpd 虚拟用户及目录
    ubuntu server 安装 mantis bug tracker 中文配置
    ubuntu server vsftpd 匿名用户上传下载及目录设置
    linux 用户管理,用户权限管理,用户组管理
  • 原文地址:https://www.cnblogs.com/whiteBear/p/12632241.html
Copyright © 2011-2022 走看看