整体思路:一个循环队列同时使用节点的计数来标记节点的新旧信息,如果有新节点加入时,就把最旧的节点清空,将新节点加入。具体画一下图比较好理解。
#include <iostream>
#include <vector>
#include <map>
#include <queue>
using namespace std;
static const int LEN = 5;
int main(){
vector<int> vires(LEN,-1);//保存结果
vector<int> vi(LEN,-1);//循环数组
deque<int> empty;//上层为空的结点在结果数组中的下标
map<int,int> mii,miires;//mii记录vi里的点的计数,miires记录的是点在vires里的下标
for(int i=0;i<LEN;++i){
empty.push_back(i);
}
int itp,ict=0;
while(cin>>itp){
if(mii.count(vi[ict])){//如果存在,删除循环队列中原来的数
--mii[vi[ict]];
if(mii[vi[ict]]==0){
empty.push_back(miires[vi[ict]]);
mii.erase(mii.find(vi[ict]));
}
}
vi[ict]=itp;//给循环队列中当前位置赋新值
mii[itp]+=1;
++ict;
ict%=LEN;
if(miires.count(itp)){
auto atp = empty.begin();
for(;atp!=empty.end();++atp){
if(*atp==miires[itp]) break;
}
if(*atp == miires[itp]) empty.erase(atp);
}
else{//真实存储中没有这个数,需要存进去
if(vires[empty.front()]!=-1) miires.erase(miires.find(vires[empty.front()]));
vires[empty.front()]=itp;
miires[itp]=empty.front();
empty.pop_front();
//print
for(auto ieh:vires){
if(ieh!=-1)
cout<<ieh<<" ";
}
cout<<endl;
}
}
return 0;
}
//1 2 3 4 5 6 5 4 3 1 7 9 1 2 3 5 6 9 4 2 1
结果如下:
1 2 3 4 5 6 5 4 3 1 7 9 1 2 3 5 6 9 4 2 1
1
1 2
1 2 3
1 2 3 4
1 2 3 4 5
6 2 3 4 5
6 1 3 4 5
7 1 3 4 5
7 1 3 4 9
7 1 3 2 9
5 1 3 2 9
5 1 3 2 6
5 9 3 2 6
5 9 3 4 6
5 9 2 4 6
1 9 2 4 6
这个实现中有些地方需要在数组中查找元素,效率差就差在这里,如果需要时间复杂度为O(1)的插入与删除,还是得用hashMap+双向链表。