思路1:模拟,用链表或者一个队列即可实现,但时间复杂度过高。
思路2: 数学推理
设 f(n,m)表示长度为n的序列,每次删除第m个以后,最后剩下的数字。
那么,第一个删除的应该是(m-1)%n ,设k=(m-1)%n
那么剩下的序列应该是 k+1 ,k+2 ....n-1, 0 ,1 ,....k-1 序列有n-1个数
接下来应该做的是对上面的序列求F(n-1,m) ,这里之所以用F,而不用f。是因为序列已经发生了变化。
如果我们能将序列转成从 0开始的n-1个数,那么就可以使用 f(n-1,m) 了。
如何做呢?我们来看一下映射关系。
k+1 对应 0
k+2 对应1
k+3 对应 2
......
k-1 对应 n-1
如何实现上述的转换? (x-k-1)%n 即可,其中x表示(k+1,k+2.....)
但其实我们需要的是从0,1,...n-1到k+1,k+2的映射关系
即 (x+k+1)%n,也就是说,我只要在f(n-1,m)中求出剩下的那一个数,通过(x+k+1)%n 就可以转回来,它在原序列中对应的数。
所以可以递归实现。(x+k+1)%n == ((f(n-1,m)+(m-1)%n+1)%n == (f(n-1,m)+m)%n
class Solution {
public:
int lastRemaining(int n, int m) {
return f(n,m);
}
int f(int n,int m)
{
if(n==1)
{
return 0;
}
return (f(n-1,m)+m)%n;
}
};