
\qquad这道题对时间复杂度的要求比较高,最多O(logN),考察的点就两个:
\qquad\qquad 1. 数据结构的使用(queue、deque、set、map、tuple)
\qquad\qquad 2. 二分查找
\qquad要求source、destination、timestamp三属性的组合保持唯一、不能重复,可以想到利用Map进行快速查找,但由于三个属性共同组成一个单元,使用哪个作为Key都不能快速定位。转而考虑利用Set进行查找,其存储的元素为三个属性的集合,即tuple<int,int,int>。tuple获取某个位置的元素使用get<n>(tuple),n为元素的位置,从0开始。
\qquad对比一下map与set:
| 项目 | Map | Set | unordered_map |
|---|---|---|---|
| 底层结构 | 红黑树 | 红黑树 | 哈希映射表 |
| 增删改查复杂度 | O(log N) | O(log N) | O(1) |
| 有序性 | key值升序 | 元素升序 | 无序 |
| 唯一性 | key唯一、value可重复、更改 | 元素唯一,不可更改 | key唯一、value可重复、更改 |
队列有两种结构可以选择,队列(queue)和双端队列(deque),可按需选择:
\qquadqueue是仅提供简单的push、pop、front、back接口,不支持迭代器遍历,适用于FIFO的简单任务;
\qquaddeque是升级版,底层为分段数组,支持双端操作、随机访问deque[i]、与迭代器遍历等,适用于需要双端操作的复杂任务。
\qquad题目中为了快速找到同一 destination对应的时间序列,可以通过使用unordered_map<destination, deque<timestamp>>的方式快速找到。
\qquad最后便是二分了,还是要熟悉while写法。要找[startTime, endTime]区间内的的元素个数,可以分别写两个函数找到开头和结尾的元素位置,计算二者间的距离即可。
\qquad二分的通用模版总结,
\qquad\qquadwhile的循环条件为 l < r
\qquad\qquad==的情况与大于或小于合并(由else覆盖)
\qquad\qquad按照if更新一边的值(l/r = mid+1/-1),else内不再更新,直接使用l/r = mid
\qquad\qquad按照不同的更新方式,选择mid上取整/下取整,具体可以考虑r == l+1的情况,根据不同值看是否会陷入死循环来选择取整方式。
\qquad上、下取整的终极实现方式:(看起来麻烦,但是可以防止溢出)
\qquad\qquad下取整:l + (r - l) / 2
\qquad\qquad上取整:l + (r - l + 1) / 2
\qquad最后得到的位置还需要检查一下找到的下标是否满足要求。
代码如下:
typedef tuple<int,int,int> T;
typedef deque<int> V;
class Router {
public:
set<T> packs;
unordered_map<int,V> m;
queue<T> que;
int limit = 0;
Router(int memoryLimit) {
limit = memoryLimit;
}
bool addPacket(int source, int destination, int timestamp) {
T t1(source, destination, timestamp);
if(packs.contains(t1)) return false;
if(que.size() > limit-1)
{
T t2 = que.front();
que.pop();
m[get<1>(t2)].pop_front();
packs.erase(t2);
}
packs.insert(t1);
m[destination].push_back(timestamp);
que.push(t1);
return true;
}
vector<int> forwardPacket() {
vector<int> ans;
if(que.size() > 0)
{
T t1 = que.front();
ans.push_back(get<0>(t1));
ans.push_back(get<1>(t1));
ans.push_back(get<2>(t1));
que.pop();
m[get<1>(t1)].pop_front();
packs.erase(t1);
}
return ans;
}
int findStart(V& q, int target)
{
int l = 0, r = q.size();
int mid = 0;
while(l < r)
{
mid = l + (r - l)/2;
if(q[mid] < target) l = mid+1;
else r = mid;
}
return l;
}
int findEnd(V& q, int target)
{
int l = 0, r = q.size()-1;
int mid = 0;
while(l < r)
{
mid = l + (r - l + 1) /2;
if(q[mid] > target) r = mid-1;
else l = mid;
}
return l;
}
int getCount(int destination, int startTime, int endTime) {
int ans = 0;
int start = findStart(m[destination], startTime);
int end = findEnd(m[destination], endTime);
if(m[destination][start] >= startTime && m[destination][end] <= endTime) ans = end-start+1;
return ans;
}
};
/**
* Your Router object will be instantiated and called as such:
* Router* obj = new Router(memoryLimit);
* bool param_1 = obj->addPacket(source,destination,timestamp);
* vector<int> param_2 = obj->forwardPacket();
* int param_3 = obj->getCount(destination,startTime,endTime);
*/


943

被折叠的 条评论
为什么被折叠?



