跳转至

62.圆圈中最后剩下的数字 (Medium)*

题目描述*

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

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

限制*

1 <= n <= 10^5, 1 <= m <= 10^6

代码*

可以用链表模拟,不过超时了。。。所以也不太知道模拟写的对不对,样例倒是通过了。

数学方法,n 个数字,不断删除 m,将最后剩下的数字记为 f(n, m),n 个数字中第一个被删除的应该是 (m - 1) \mod n,记为 k

经过第一次删除后,从 k + 1 开始计数,因此原来的位置被映射为:

原始 映射
k + 1 0
k + 2 1
... ...
n - 1 n - k - 2
0 n - k - 1
... ...
k - 1 n - 2

原下标 y,映射后下标 x,可得到 x \equiv (y - k - 1) \mod n \Rightarrow y \equiv (x + k + 1) \mod n

n - 1 个数字,删除第 m 个数字,剩下的是 f(n - 1, m)。将其还原回原始数字即 (f(n - 1, m) + k + 1) \mod n,也就是 f(n, m)

由此得到递推公式:

f(n, m) = (f(n - 1, m) + k + 1) \mod n \\ \overset{k \equiv (m - 1) \mod n}{\Longrightarrow} f(n, m) = (f(n - 1, m) + m) \mod n, f(1, m) = 0
class Solution {
public:
    int lastRemaining(int n, int m) {
        int res = 0;
        for(int i = 2; i <= n; i++) {
            res = (res + m) % i;
        }
        return res;
    }
};

最后更新: July 23, 2022