圆圈中最后剩下的数字:约瑟夫环

文章讲解了如何使用递归和迭代方法求解LeetCode题目中的圆圈中最后剩下的数字问题,通过函数f(n,m)建模,详细解释了递归关系并提供了两种实现方式:递归版本和迭代版本,以及特殊情况下返回值的处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

力扣题目 剑指 Offer 62. 圆圈中最后剩下的数字

对于 官方题解 进行了一定的修改和补充。

数学 + 递归

将问题建模为函数 f(n, m),函数的返回值为最终留下的元素的序号

长度为 n 的序列会先删除第 m % n 个元素,然后剩下一个长度为 n - 1 的序列。假设对于剩下的 n - 1 个元素,最终会留下第 x 个元素,即 x = f(n - 1, m)。也就是说,对于长度为 n 的序列,删除第 m % n 个元素后,继续向后数了 x 个元素,为最终剩下的元素。因此有 f(n, m) = (m % n + x) % n = (m + x) % n

递归计算 f(n, m), f(n - 1, m), f(n - 2, m), ... 直到递归的终点 f(1, m)。当序列长度为 1 时,一定会留下唯一的那个元素,它的编号为 0。

class Solution {
    int f(int n, int m) {
        if (n == 1) {
            return 0;
        }
        int x = f(n - 1, m);
        return (m + x) % n;
    }
public:
    int lastRemaining(int n, int m) {
        return f(n, m);
    }
};

递归改写为迭代

f(1, m) = 0 开始迭代,直到 f(n, m)。根据上文的 f(n, m) = (m + x) % n,可以得到:

f(2, m) = (m + f(1, m)) % 2
f(3, m) = (m + f(2, m)) % 3
···
f(n, m) = (m + f(n - 1, m)) % n

i[2, n],迭代公式为 f = (m + f) % i

class Solution {
public:
    int lastRemaining(int n, int m) {
        int f = 0;
        for (int i = 2; i <= n; i++) {
            f = (m + f) % i;
        }
        return f;
    }
};

注意到有的题编号从 1 开始,直接在 return 的结果上加 1 就好了。

有的题有特殊用例,序列长度 n0,题中会提示这种情况返回 -1

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值