剑指 Offer 62:圆圈中最后剩下的数字

剑指 Offer 62:圆圈中最后剩下的数字,第1张

剑指 Offer 62:圆圈中最后剩下的数字

剑指 Offer 62:圆圈中最后剩下的数字
  • 题目
  • 解题
    • 方法一:动态规划

题目

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

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

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

示例 2:

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

解题

由于m,n的数量级很大,使用链表模拟直接超时了,时间复杂度是O(mn),所以不能使用这种方法。

方法一:动态规划

参考链接1
参考链接2


也就是说f(n,m)删掉第一个元素,(m-1)%n=t-1后,起始位置是m%n=t,那么就是f(n-1,m)的问题了。
由于利用动态规划,已知了f(n-1,m)删除的位置,由下图可以知道f(n,m)删除后,就是f(n-1,m)问题向后平移了一个t。
也就是说在f(n-1,m)问题中x的位置,对应于 f(n,m)中x+t的位置,也就是
(x+t)%n
=(x+m%n)%n
=(x+m)%n

又由于f(1,m)只有1个数,因此就剩余第一个数0,于是初始化dp[1]=0;

class Solution {
public:
    int lastRemaining(int n, int m) {
        vector dp(n+1);
        dp[1]=0;
        for(int i=2;i<=n;i++){
            dp[i]=(dp[i-1]+m)%i;
        }
        return dp[n];
    }
};

更加简洁点,vector可以用一个变量来代替

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

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5636494.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-16
下一篇 2022-12-16

发表评论

登录后才能评论

评论列表(0条)

保存