问题描述:0,1,n-1这n个数字排成一个圆圈,从数字0开始,每次从这个圆圈里删除第m个数字。求出这个圆圈里剩下的最后一个数字。
这是力扣上的一道题。我的思路:
- ①首先想到的是用循环链表,每次向后遍历找到第m个节点,从链表中删除,再找下一个第m个节点再删除,直到链表中剩下一个节点。但是链表不支持随机访问,每次访问往后的第m个结点也是很费时的。
- ②然后想到用数组,数组支持随机读取,可以直接通过下标访问下一个第m个节点,但删除一个元素后,移动剩下元素要耗费大量时间。
- ③那有没有用数组但又不删除元素的方法呢。每删除一个数,就把这个元素值置为-1,每经过m个不为-1的数,就把这个数值置为-1,直到数组中只剩下一个不为-1的元素,这个元素值就是答案。(这种方法效率和链表比起来也差不多)
第③种方法虽然有数组的随机访问速度,也不用删除元素,但数据量大的时候,运行到后面数组内有大量值为-1的元素,要进行多次循环判断,速度也很慢,提交后直接超时。官方给出的是数学方法,找出问题的递归公式,几行代码解决。
- ④数学方法(递推公式为 f(N,M)=(f(N−1,M)+M)%N ),数学公式如何推出来的见博客约瑟夫环——公式法(递推公式)
附上代码:
第①中方法(使用链表):
// 定义链表的节点
struct node{
int val;
node *next;
node(int val_,node *next_=nullptr){
val=val_;
next=next_;
}
};
class Solution {
public:
int LastRemaining_Solution(int n, int m){
if(n<=0 || m<=0)