- 题目
- 解题
- 方法一:动态规划
题目链接
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) { vectordp(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; } };
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)