参考题解 by leetcode- Vancomycin
题目描述
难度:简单
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
解题分析
定义状态 dp(n,m) 为长度为n的序列 (0 - n-1
)不断删除第m个元素最后剩下的元素下标;
假设 n = 5 m = 3,此时有所求序列 0 1 2 3 4, 当尝试进行第一轮删除之后;
此时序列长度变为 n - 1,状态更新为 dp(n-1,m),序列为 3 4 0 1;
即元素2也就是第m个元素被删除(下标为m-1),而下一轮的开头变成了 3 ,即下标为m的元素;
以上是dp(5,3)经过第一轮删除后变为dp(n-1,m)之后的序列状态,为了区分正常状态,该状态暂定为 dp’(n-1,m);
当 n = 4, m = 3 时,状态为dp(n-1,m),序列为 0 1 2 3;
此时有dp’(n-1,m)对应序列 3 4 0 1 , dp(n-1,m)对应序列 0 1 2 3,两者对应表格如下:
dp(n-1,m) | 0 | 1 | … | n-m-1 | n-m | … | n-3 | n-2 |
dp’(n-1,m) | m | m+1 | … | n-1 | 0 | … | m-3 | m-2 |
可见对应关系有 dp’(n-1,m) = ( dp(n-1,m) + m) % n;
由于 dp(n,m) == dp’(n-1,m),即二者最终结果是一致的。
所以有状态转移方程 dp(n,m) = ( dp(n-1,m) + m) % n
,需要注意的是,n为当前序列长度。
当n = 1时,序列所剩元素下标为0。
code
public int lastRemaining(int n, int m){
int ans = 0; // dp(1,m)
for(int i = 2; i <= n; ++i) ans=(ans+m)%i; // dp(i,m) = (dp(i-1,m)+m)%i
return ans;
}
总结
这题困扰了我好久,lc有很多题解我都没有看懂,只能说我能力太差了。。。
幸好看到了一篇我能看懂的题解(救大命)特此结合自己的想法记录一下该题解。
岁月悠悠,衰微只及肌肤;热忱抛却,颓废必致灵魂