Q:0~n-1这n个数字围成一个圆圈,每次删除圈内的第m个数字,求圆圈内最后一个剩下的数字
解法一:list容器+迭代器
解题思路:
- 因为要每次删除一个数字,并且要遍历,因此需要找到一个方便遍历并且删除效率高的容器;这里我们使用list容器,因为它的删除效率高并且支持迭代器,我们用list模拟环
- 首先将n个数字尾插进list中
- 再使用迭代器开始遍历,每次从当前位置走m-1步就到达第m个数字,如果走到迭代器end位置,则从begin位置开始继续走(模拟环的过程)
- 用一个新的迭代器记录要删除的节点的下一个位置即为下次开始走的位置,再删除当前节点
图解:
代码:
class Solution {
public:
int LastRemaining_Solution(int n, int m)
{
if(n<1||m<1)
return -1;
list<int> ls;
for(int i=0;i<n;++i)
{
ls.push_back(i);
}
list<int>::iterator cur=ls.begin();
while(ls.size()>1)
{
for(int i=0;i<m-1;++i)
{
++cur;
if(cur==ls.end())
cur=ls.begin();
}
++cur;
list<int>::iterator next=cur;
if(next==ls.end())
next=ls.begin();
--cur;
ls.erase(cur);
cur=next;
}
return *cur;
}
};
解法二:用链表节点模拟环的过程
解题思路:
- 用节点将元素连起来,最后一个节点指向首节点
- 要注意的是,在走的时候要走m-2步,让当前节点的下一个节点指向下下个节点(等同于把第m个节点删除了)
代码:
class listNode{
public:
int val;
listNode* next;
listNode(int val)
{
this->val=val;
}
};
class Solution {
public:
int LastRemaining_Solution(int n, int m)
{
if(n<1||m<1)
return -1;
listNode* head=new listNode(0);
listNode* cur=head;
listNode* tmp;
for(int i=1;i<n;++i)
{
tmp=new listNode(i);
cur->next=tmp;
cur=tmp;
}
tmp->next=head;
listNode* res;
while(n>1)
{
res=head;
for(int i=1;i<m-1;++i)
{
res=res->next;
}
res->next=res->next->next;
head=res->next;
--n;
}
return res->val;
}
};