题目描述
每年六一儿童节,牛客都会准备一些小礼物去看望孤儿院的小朋友,今年亦是如此。HF作为牛客的资深元老,自然也准备了一些小游戏。其中,有个游戏是这样的:首先,让小朋友们围成一个大圈。然后,他随机指定一个数m,让编号为0的小朋友开始报数。每次喊到m-1的那个小朋友要出列唱首歌,然后可以在礼品箱中任意的挑选礼物,并且不再回到圈中,从他的下一个小朋友开始,继续0...m-1报数....这样下去....直到剩下最后一个小朋友,可以不用表演,并且拿到牛客名贵的“名侦探柯南”典藏版(名额有限哦!!^_^)。请你试着想下,哪个小朋友会得到这份礼品呢?(注:小朋友的编号是从0到n-1)
Solution 1
//标志计算法
class Solution {
public:
int LastRemaining_Solution(int n, int m)
{
int state[n];
int cnt,cur=0;
fill(state,state+n,0);
for(int i=0;i<n-1;++i)
{
cnt=1;
while(cnt<=m)
{
if(!(i==0&&cnt==1))
{
while(state[(cur+1)%n]!=0)
cur=(cur+1)%n;
cur=(cur+1)%n;
}
++cnt;
}
state[cur]=1;
}
for(int i=0;i<n;++i)
if(state[i]!=1) return i;
return -1;
}
};
Solution 2
//模拟循环数组
class Solution {
public:
int LastRemaining_Solution(int n, int m)
{
if(n<=0) return -1;
if(n==1) return 0;
int state[n];
fill(state,state+n,0);
int count=n,cur=-1,step=0;
while(count>0)
{
++cur;
if(cur>=n) cur=0;
if(state[cur]!=0) continue;
++step;
if(step==m)
{
state[cur]=1;
step=0;
--count;
}
}
return cur;
}
};
Solution 3(非常重要)
可以采用循环链表: 原理和循环数组一样,当最后链表只剩下一个元素时,输出索引。
class Solution {
typedef struct node
{
int val;
node *next;
node(int x):val(x),next(nullptr){}
}*Node;
public:
Node create(int n)
{
Node pHead=new node(-1);
Node p=pHead;
for(int i=0;i<n;++i)
{
Node q=new node(i);
q->next=p->next;
p->next=q;
p=q;
}
p->next=pHead->next;
return pHead;
}
int LastRemaining_Solution(int n, int m)
{
if(m<=0||n<=0) return -1;
Node head,p,q;
head=create(n);
p=head->next;
delete head;
int cnt=0;
while(p->next!=p)
{
q=p->next;
++cnt;
if(cnt>=m-1)
{
cnt=0;
p->next=q->next;
delete q;
}
p=p->next;
}
int res=p->val;
delete p;
return res;
}
};