题目
链表 + 哈希表
思路
有点像内存管理算法,比如 L R U LRU LRU 之类的,其相同点在于出队的位置是不确定的,不一定是队首元素出队,而是队列中的任何一个元素都有可能出队
对于这种问题,队列就不能用数组来模拟了,因为删除元素很麻烦,而且由于不确定出队元素的位置,所以应该用一个哈希表来记录
对于这道题,题目求的是不插队的人数,也就是正常入队正常出队的人数。
当 A A A 比 B B B 先入队,但是 B B B 却比 A A A 先出队,则说明 B B B 一定是插队的。然而我们并不需要去确定 B B B 到底插在了队列的哪个位置,而是关注其出队的时候是不是队首即可。如果 B B B 出队的时候不是队首,则说明 B B B 是插队的,所以,我们只需要统计元素出队的时候是队首的个数即可。
代码
#include <iostream>
#include <list>
#include <string>
#include <unordered_map>
using namespace std;
int main(void) {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t = 0, n = 0, ans = 0;
cin >> t;
string op, s;
// 链表队列,降低删除复杂度
list<string> q;
// 哈希表以名字为键,以链表结点为值,目的是在某个人出队的时候方便确定这个人在链表中的哪个位置以便删除
unordered_map<string, list<string>::const_iterator> mp;
while (t--) {
cin >> n;
// 对每一组用例都要清洗容器
ans = 0;
q.clear();
mp.clear();
while (n--) {
cin >> op >> s;
if (op[0] == 'i') {
q.emplace_back(s);
// 注意添加的不是 end(),而是 end() 的前一个迭代器
mp[s] = prev(q.end());
} else if (op[0] == 'o') {
if (q.front() == s) {
// 出队时如果恰好是队首,则说明是排队的乖娃娃,答案加1
ans++;
}
// 出队
q.erase(mp[s]);
}
}
cout << ans << endl;
}
return 0;
}