面试题62. 圆圈中最后剩下的数字(Leetcode每日一题-2020.03.30)

Problem

0,1,n-1这n个数字排成一个圆圈,从数字0开始,每次从这个圆圈里删除第m个数字。求出这个圆圈里剩下的最后一个数字。

例如,0、1、2、3、4这5个数字组成一个圆圈,从数字0开始每次删除第3个数字,则删除的前4个数字依次是2、0、4、1,因此最后剩下的数字是3。

Example1

输入: n = 5, m = 3
输出: 3

Example2

输入: n = 10, m = 17
输出: 2

Solution

Solution1

模拟法,超时

将[0,n]依次存储在双端队列中
只要队列的长度不为1,就一直循环:如果到了第m个就remove;否则将其添加到链表尾部
时间复杂度为O(nm)

class Solution {
public:
    int lastRemaining(int n, int m) {
        deque<int> dq;
        for(int i = 0;i<n;++i)
            dq.push_back(i);
        while(dq.size() > 1)
        {
            int j = 0;
            while(j < m-1)
            {
                int tmp = dq.front();
                dq.pop_front();
                dq.push_back(tmp);
                ++j;
            }
            dq.pop_front();
        }

        return dq.front();

    }
};

Solution1.5

假设当前删除的位置是 idxidx ,下一个删除的数字的位置是 idx + midx+m 。但是,由于把当前位置的数字删除了,后面的数字会前移一位,所以实际的下一个位置是 idx + m - 1idx+m−1。由于数到末尾会从头继续数,所以最后取模一下,就是 (idx + m - 1) \pmod n(idx+m−1)(modn)。

class Solution {
public:
    int lastRemaining(int n, int m) {
        deque<int> dq;
        for(int i = 0;i<n;++i)
            dq.push_back(i);
        int idx = 0;
        while(n > 1)
        {
            idx = (idx + m - 1) % n;
            dq.erase(dq.begin() + idx);
            --n;
        }

        return dq.front();

    }
};

Solution2

公式法

class Solution {
public:
    int lastRemaining(int n, int m) {
        int ans = 0;
        // 最后一轮剩下2个人,所以从2开始反推
        for (int i = 2; i <= n; i++) {
            ans = (ans + m) % i;
        }
        return ans;

    }
};

你可能感兴趣的:(leetcode数学)