剑指offer第46题


题目描述:

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

这道题目我们稍加分析就能感觉到在C#中利用集合是非常好做的,首先将从零到n-1个孩子编号按顺序在List中Add,然后再通过集合的RemoveAt方法来遍历每次循环报数后的那个孩子编号并删去,同时将标记顺序也向前移一格继续数数遍历索引;
ps:我在书写时在num索引记录一开始为零总是出错后来才发现如果从零开始报数的话,还没开始循环的时候就应该让记录下表前移一个才能保证每次开始都不漏掉人而且把号码对齐;
另外这个题目还有很简单的递归公式不做详解了
f[1]=0;
f[i]=(f[i-1]+m)%i; (i>1)
通过递推公式即可求得f[n]。//最为简单的解法

这里主要为了巩固一下集合的知识

using System;
using System.Collections.Generic;
class Solution
{
    
    
    public int LastRemaining_Solution(int n, int m)
    {
    
    
        // write code here
        if(n<=0||m<=0)
            return -1;//如果是不符合题意返回-1;
        List<int> res = new List<int>();
        for(int i=0 ; i<n ; i++)
            res.Add(i);
        int num=-1;  //创建集合并赋值初始化编号,同时因为0号也是一个孩子所以我们
        while(res.Count>1)//初始化标记为-1这样开始遍历的时候num++就确保了第一次0的情况记录下来了
        {
    
       for(int j=0 ; j<m ; j++)
            {
    
    
                num++;
                if(num>=res.Count)
                    num=0;                
            }            
            res.RemoveAt(num);
            num--;  //因为删去了num下标的学生所以之后的孩子都前移了一格但我们的j是从0开始
                    //所以需要继续索引前移一个确保下一次遍历数数时从0开始否则的话
        }           //否则没有自减的话,会导致下一次遍历直接跳过了一个孩子但他是没有记录在报数
        return res[0];
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_50746193/article/details/120424607