孩子们的游戏(圆圈中最后剩下的数)

本题来自NowCoder网《剑指offer》:
每年六一儿童节,NowCoder都会准备一些小礼物去看望孤儿院的小朋友,今年亦是如此。HF作为NowCoder的资深元老,自然也准备了一些小游戏。其中,有个游戏是这样的:首先,让小朋友们围成一个大圈。然后,他随机指定一个数m,让编号为0的小朋友开始报数。每次喊到m的那个小朋友要出列唱首歌,然后可以在礼品箱中任意的挑选礼物,并且不再回到圈中,从他的下一个小朋友开始,继续0…m-1报数….这样下去….直到剩下最后一个小朋友,可以不用表演,并且拿到NowCoder名贵的“名侦探柯南”典藏版(名额有限哦!!^_^)。请你试着想下,哪个小朋友会得到这份礼品呢?
最开始也是没头绪,有想到用递归的思路去解决,但是它传入的参数是一个int n ,int m,n代表人数,m代表报数。递归不能去破坏人员的编号,这里是比较难处理的问题。最终我构造了一个新的方法用一个数组去维护,将编号定义为Integer的数据,这样用集合去递归,而不是用int n去递归。

public int LastRemaining_Solution(int n, int m) {
        if(n == 0) return -1;
        if(n == 1) return 0;
        else {
            // 创造一个数组,去初始化这个list
            List list = new ArrayList<Integer>();
            for(int i = 0;i < n;i ++){
                list.add(i);
            }
            // 调用新的方法
            return getRemaining(list, m);
        }
    }
    private int getRemaining(List<Integer> list,int m) {
        // 递归出口,剩下一个元素,返回该元素
        if(list.size() == 1) return list.get(0);
        // 获取出队的人员数组下表
        int index = m % list.size() == 0 ? list.size() - 1:(m % list.size() - 1);
        // 新建一个list用于递归
        List<Integer> tempList = new ArrayList<Integer>();
        for(int i = index + 1;i < list.size();i ++) {
            tempList.add(list.get(i));
        }
        for(int i = 0;i < index;i ++){
            tempList.add(list.get(i));
        }
        return getRemaining(tempList, m);
    }

后来看了别人讨论,这是一个约舍夫问题,用很简单的递归代码去实现了,主要是找到递归的规律。

 int LastRemaining_Solution(unsigned int n, unsigned int m)
    {
        if(n==0)
            return -1;
        if(n==1)
            return 0;
        else
            return (LastRemaining_Solution(n-1,m)+m)%n;
    }

你可能感兴趣的:(孩子们的游戏(圆圈中最后剩下的数))