剑指offer:面试题45——圆圈中最后剩下的数字

博客围绕剑指offer面试题45,即圆圈中最后剩下的数字问题展开。介绍了一个小朋友围成圈报数选礼物的游戏,给出两种解题思路,一是用list模拟循环链表或数组计算,二是基于约瑟夫问题的递归解法,还给出循环实现的公式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

剑指offer:面试题45——(孩子们的游戏)圆圈中最后剩下的数字

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

思路一:如果可以允许使用stl,采用list模拟一个循环链表,每次退出一个人,则erase掉这个人,最终看留下了谁。如果不允许使用循环链表,可以采用数组的方式计算

思路二:这个问题产生于约瑟夫问题,第一次人数是0~n-1,当退出了m-1人时,序列下一次从m开始算起,即m,m+1,m+2…n-1,0,1,…m-2

如果对这个序列重新映射为0~n-2,可以发现问题又被归结为上一次问题求第m个退出的人,因此是个递归问题。加入映射关系设为f,则每次退出的人为f(x) = (x-m-1)%n ,那么我们反推,假如已知这次退出的人为x,那么他在圆圈中的位置编号根据映射的逆应该为(x+m+1)%m

即:

f(n,m)= 0 n=1

​ [f(n-1),m]%n n>1

如果用循环实现,可以理解为,每次剩下i个人,最后是ret位置的人没有退出,根据映射,上一次它在这个圆圈中被重新编号的位置为

ret=(ret+m)%i ,总共进行了n轮游戏,因此在n个人进行游戏,即第一轮游戏时,它的位置为i从n循环得到的ret的值

        /*
        //循环队列法
        if(n<1||m<1) return -1;
        int i=0;
        list<int> numbers;
        for(i=0;i<n;i++)
        {
            numbers.push_back(i);
        }
        list<int>::iterator ite=numbers.begin();
        while(numbers.size()>1)
        {
            for(int i=0;i<m-1;i++)   //遍历找到第m-2个位置。因为第m-1个人出列下标实际上是m-2
            {
                ite++;
                if(ite==numbers.end())
                    ite=numbers.begin();
            }
            list<int>::iterator next=++ite;   //next指向下一个,先++再赋值,保存下一节点
            if(next==numbers.end())
                next=numbers.begin();
            --ite;    //指回要删除的节点
            numbers.erase(ite);   //调用erase删除结点
            ite=next;
        }
        return *ite;
        */
        if(n<1||m<1)return -1;
        int ret=0;
        int i;
        for(i=1;i<=n;i++)    //最后剩下一个人,总共n个人进行游戏
            ret=(ret+m)%i;
        return ret;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值