前言
这是一道有关链表应用的题目,非常经典。主要用到了链表的特性,即可以非常高效的进行插入和删除操作,和迭代器的应用。
一、题目描述
一队士兵报数:从头开始进行1至2报数,凡报到2的出列,剩下的向小序号方向靠拢,再从头开始进行1至3报数。凡报到3的出列,剩下的向小序号方向靠拢,以后从头开始轮流进行1至2报数、1至3报数,直到剩下的人数不超过,3人为止。
二、解析
首先题目中个人感觉有一个容易混淆的地方,这里的出列是在一整轮的报数完成后,再一起出列。
比如第一轮报数中:
人员编号为:1 2 3 4 5 6 7 8
报数:1 2 1 2 1 2 1 2
进行出列操作
第二轮报数中:
人员编号为:1 3 5 7
报数:1 2 3 1
进行出列操作
最终序列:1 3 7
数据结构上:推荐使用链表结构,因为需要频繁的涉及在序列的某一位置进行删除,链表的特点就是可以快速的进行插入和删除。
算法上:就按照样例中的那样,通过for循环将报数为2或3的结点删除
三、具体代码
#include<bits/stdc++.h>
using namespace std;
int main()
{
int t,n;
cin>>t;
while(t--)
{
cin>>n;
list<int> q;
list<int>::iterator it;
for(int i=1;i<=n;i++)
{
q.push_back(i);
}
int k=2; //初始值为2,表示以2为最大值进行报数
while(q.size()>3)
{
int num=0;
for(it=q.begin();it!=q.end();)
{
num++; //每次遇到能整除k就进行出列处理
if(num%k==0)
{
it=q.erase(it); //erase返回指向删除元素的下一个元素的迭代器
}
else
{
it++;
}
}
k==2?k=3:k=2; //一次循环遍历结束,将k换成另一个值
}
for(it=q.begin();it!=q.end();it++)
{
if(it!=q.begin())
{
cout<<" ";
}
cout<<*it;
}
cout<<endl;
}
return 0;
}