剑指 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<int> 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;
    }
};


相关文章
|
8月前
剑指 Offer 11:旋转数组的最小数字
剑指 Offer 11:旋转数组的最小数字
59 1
|
8月前
剑指 Offer 50:第一个只出现一次的字符
剑指 Offer 50:第一个只出现一次的字符
41 0
|
8月前
剑指 Offer 29:顺时针打印矩阵
剑指 Offer 29:顺时针打印矩阵
45 0
|
8月前
剑指 Offer 32:从上到下打印二叉树
剑指 Offer 32:从上到下打印二叉树
48 0
|
8月前
剑指 Offer 17:打印从1到最大的n位数
剑指 Offer 17:打印从1到最大的n位数
37 0
|
8月前
剑指 Offer 42:连续子数组的最大和
剑指 Offer 42:连续子数组的最大和
45 0
剑指offer 70. 圆圈中最后剩下的数字
剑指offer 70. 圆圈中最后剩下的数字
79 0
|
Java Python
leetcode每日一题.面试题62:圆圈中最后剩下的数字
leetcode每日一题.面试题62:圆圈中最后剩下的数字
70 0
Leecode 面试题62. 圆圈中最后剩下的数字
Leecode 面试题62. 圆圈中最后剩下的数字
77 0