双端链表<--->环形链表,stl库中 list<int>的使用

本文介绍了一种在六一儿童节上进行的游戏,通过两种不同的方法来找出最终获胜的小朋友编号。一种方法使用了C++的list容器进行模拟,另一种则是通过数学公式直接计算结果。

题目描述

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

解法一:
先看两条规制:
1、对于节点式容器(map, list, set)元素的删除,插入操作会导致指向该元素的迭代器失效,其他元素迭代器不受影响。
2、对于顺序式容器(vector)元素的删除、插入操作会导致指向该元素以及后面的元素的迭代器失效。

时间复杂度极高O(mn)
class Solution {
public:
    int LastRemaining_Solution(int n, int m)
    {
        if(n<1||m<1) return -1;
        list<int> members;
        for (int i = 0; i < n; ++i) members.push_back(i);
        list<int>::iterator it=members.begin();
        int cnt=0;
        for(;members.size()>1;)
        {
            cnt++;
            if(cnt==m){
                members.erase(it++);//it指向的迭代器失效,所以把它指向下一个。这里有个技巧,自行体会。
                cnt=0;
            }else{
                ++it;//
            }
            if(it==members.end())
                it=members.begin();
        }
        return *(members.begin());
       
    }
};

解法二:数学解法
利用递推公式直接算出结果。第一个删除的是(m-1)%n,设最后剩余f(n,m)
0 1 2 ........ k-1  k+1  ......n-1 
----------
k+1 k+2......n-1 0 1 2 .......k-1     
-------
0   1 2 .......n-k-2 n-k-1         n-2   

lass Solution {
public:
    int LastRemaining_Solution(int n, int m)
    {
        if(n<1||m<1) return -1;
        
        int result=0;

        for (int i = 2; i <=n; ++i)
        {
            result=(result+m)%i;
        } 
        return result;
       
    }
};









评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值