3508: Implement-Router
Medium
table of contents
I hate this question-
For the data structures used in this question, I realised that I needed multiple to be able to implement all the functionality required in the question.
- to check for unique packets, I have
uniquePackets(set<tuple<int, int, int>>) - to handle the packet forwarding in a FIFO order, I
have
packetQueue(queue<tuple<int, int, int>>)- both instances use
tuple<int, int, int>instead ofvector<int>(which is the form some functions return) becausetuplehave less overhead thanvector
- both instances use
- finally, to be able to search for packets that are currently stored
in the router with a specific destination and have timestamps
in the inclusive range
[startTime, endTime], we usepacketCount(unordered_map<int, vector<int>>)
int packetLimit;
set<tuple<int, int, int>> uniquePackets; // set<{source, destination, timestamp}>
unordered_map<int, vector<int>> packetCount; // unordered_map<destination, vector<timestamp>>
queue<tuple<int, int, int>> packetQueue; // queue<{source, destination, timestamp}>When we initialise Router, we simply need to set our
packetLimit:
Router(int memoryLimit) {
packetLimit = memoryLimit;
}For the function addPacket,
- we first define the
newPacketwe are planning to add - check if this
newPacketexists already- if it does, we can return
falseearly
- if it does, we can return
- check if
packetQueuehas reached maximum capacity- if it has, we can simply erase the first element
- add our
newPacketto the back ofpacketQueue
bool addPacket(int source, int destination, int timestamp) {
tuple<int, int, int> newPacket = {source, destination, timestamp};
if (uniquePackets.count(newPacket)) {
return false;
}
if (packetQueue.size() == packetLimit) {
auto [source, destination, timestamp] = packetQueue.front();
uniquePackets.erase(packetQueue.front());
packetCount[destination].erase(packetCount[destination].begin());
packetQueue.pop();
}
uniquePackets.insert(newPacket);
packetQueue.push(newPacket);
packetCount[destination].push_back(timestamp);
return true;
}Now, for the function forwardPacket,
- we first check if
packetQueueis empty- if it is, then we simply return
{}
- if it is, then we simply return
- else, we
popthe front ofpacketQueueand return it (as avector<int>)
vector<int> forwardPacket() {
if (packetQueue.empty()) {
return {};
}
auto [source, destination, priority] = packetQueue.front();
uniquePackets.erase(packetQueue.front());
packetQueue.pop();
packetCount[destination].erase(packetCount[destination].begin());
return {source, destination, priority};
}Finally, for the getCount function, we can simply index
into our vector<int> of timestamps
present at packetCount[destination]. Then, we use
lower_bound and upper_bound to find the first
and last possible index startTime and endTime
could be placed inside of timestamps. Now, using the
difference between startPos and endPos, we can
get the count of all unsent packets with the specified
destination occuring between startTime and
endTime.
int getCount(int destination, int startTime, int endTime) {
auto& timestamps = packetCount[destination];
auto startPos = lower_bound(timestamps.begin(), timestamps.end(), startTime);
auto endPos = upper_bound(timestamps.begin(), timestamps.end(), endTime);
return int(endPos - startPos);
}code
class Router {
public:
Router(int memoryLimit) {
packetLimit = memoryLimit;
}
bool addPacket(int source, int destination, int timestamp) {
tuple<int, int, int> newPacket = {source, destination, timestamp};
if (uniquePackets.count(newPacket)) {
return false;
}
if (packetQueue.size() == packetLimit) {
auto [source, destination, timestamp] = packetQueue.front();
uniquePackets.erase(packetQueue.front());
packetCount[destination].erase(packetCount[destination].begin());
packetQueue.pop();
}
uniquePackets.insert(newPacket);
packetQueue.push(newPacket);
packetCount[destination].push_back(timestamp);
return true;
}
vector<int> forwardPacket() {
if (packetQueue.empty()) {
return {};
}
auto [source, destination, priority] = packetQueue.front();
uniquePackets.erase(packetQueue.front());
packetQueue.pop();
packetCount[destination].erase(packetCount[destination].begin());
return {source, destination, priority};
}
int getCount(int destination, int startTime, int endTime) {
auto& timestamps = packetCount[destination];
auto startPos = lower_bound(timestamps.begin(), timestamps.end(), startTime);
auto endPos = upper_bound(timestamps.begin(), timestamps.end(), endTime);
return int(endPos - startPos);
}
private:
int packetLimit;
set<tuple<int, int, int>> uniquePackets;
unordered_map<int, vector<int>> packetCount;
queue<tuple<int, int, int>> packetQueue;
};
/**
* 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);
*/