题目: 有 n个人围成一圈,顺序排号。从第一个人开始报数(从 1到 3报数),凡报到 3的 人退出圈子,问最后留下的是原来第几号的那位。(模拟)
首先讲一下思路:我们可以用链表来模拟n个同学围坐一圈,链表结点的值为他们的序号,在给n个结点赋初值之后,我们将链表的尾结点指针指向第一个结点,因此形成一个单循环链表,然后自定义一个函数,用来处理每报到3的人退出圈子这个功能,我们只需要将指针指向该结点的next->next结点,即实现了报数到3到3的人退出圈子的功能,而且链表的循环特性不变。
//头节点结构定义如下:
struct ListNode {
int val;
struct ListNode *next;
ListNode(int n):val(n),next(nullptr){}
};
//一下是实现数到3退出圈子的函数实现:
int Func(ListNode* head,ListNode* rear,int n)
{
//num为叫号,用来判断下一个同学是否为第三个
//ans为删除的人数计数,当ans小于总人数n时,一直循环
int num=0,ans=0;
//p指向当前结点,r指向当前结点的上一结点
ListNode *p=head,*r=rear;
while(ans<n-1)
{
num+=1;
if(num%3==0)
{
ans+=1;
r->next=p->next;
p=r->next;
}else
{
r=r->next;
p=p->next;
}
}
return p->val;
}
//最后是main函数:
int main()
{
int n;
cin>>n;
ListNode *head=new ListNode(0),*r=head;
for(int i=1;i<=n;i++)
{
r->next=new ListNode(i);
r=r->next;
}
//将我们自定义的头节点删除,并将尾结点指向头节点
head=head->next,r->next=head;
cout<<Func(head,r,n);
return 0;
}