2025-09-20 Daily Challenge
Today I have done leetcode's September LeetCoding Challenge with cpp
.
September LeetCoding Challenge 20
Description
Implement Router
Design a data structure that can efficiently manage data packets in a network router. Each data packet consists of the following attributes:
source
: A unique identifier for the machine that generated the packet.destination
: A unique identifier for the target machine.timestamp
: The time at which the packet arrived at the router.
Implement the Router
class:
Router(int memoryLimit)
: Initializes the Router object with a fixed memory limit.
memoryLimit
is the maximum number of packets the router can store at any given time.- If adding a new packet would exceed this limit, the oldest packet must be removed to free up space.
bool addPacket(int source, int destination, int timestamp)
: Adds a packet with the given attributes to the router.
- A packet is considered a duplicate if another packet with the same
source
,destination
, andtimestamp
already exists in the router. - Return
true
if the packet is successfully added (i.e., it is not a duplicate); otherwise returnfalse
.
int[] forwardPacket()
: Forwards the next packet in FIFO (First In First Out) order.
- Remove the packet from storage.
- Return the packet as an array
[source, destination, timestamp]
. - If there are no packets to forward, return an empty array.
int getCount(int destination, int startTime, int endTime)
:
- Returns the number of packets currently stored in the router (i.e., not yet forwarded) that have the specified destination and have timestamps in the inclusive range
[startTime, endTime]
.
Note that queries for addPacket
will be made in increasing order of timestamp
.
Example 1:
Input:
["Router", "addPacket", "addPacket", "addPacket", "addPacket", "addPacket", "forwardPacket", "addPacket", "getCount"]
[[3], [1, 4, 90], [2, 5, 90], [1, 4, 90], [3, 5, 95], [4, 5, 105], [], [5, 2, 110], [5, 100, 110]]
Output:
[null, true, true, false, true, true, [2, 5, 90], true, 1]
Explanation
Router router = new Router(3); // Initialize Router with memoryLimit of 3.router.addPacket(1, 4, 90); // Packet is added. Return True.
router.addPacket(2, 5, 90); // Packet is added. Return True.
router.addPacket(1, 4, 90); // This is a duplicate packet. Return False.
router.addPacket(3, 5, 95); // Packet is added. Return True
router.addPacket(4, 5, 105); // Packet is added,
[1, 4, 90]
is removed as number of packets exceeds memoryLimit. Return True.router.forwardPacket(); // Return
[2, 5, 90]
and remove it from router.router.addPacket(5, 2, 110); // Packet is added. Return True.
router.getCount(5, 100, 110); // The only packet with destination 5 and timestamp in the inclusive range
[100, 110]
is [4, 5, 105]
. Return 1.Example 2:
Input:
["Router", "addPacket", "forwardPacket", "forwardPacket"]
[[2], [7, 4, 90], [], []]
Output:
[null, true, [7, 4, 90], []]
Explanation
Router router = new Router(2); // InitializeRouter
with memoryLimit
of 2.router.addPacket(7, 4, 90); // Return True.
router.forwardPacket(); // Return
[7, 4, 90]
.router.forwardPacket(); // There are no packets left, return
[]
.
Constraints:
2 <= memoryLimit <= 105
1 <= source, destination <= 2 * 105
1 <= timestamp <= 109
1 <= startTime <= endTime <= 109
- At most
105
calls will be made toaddPacket
,forwardPacket
, andgetCount
methods altogether. - queries for
addPacket
will be made in increasing order oftimestamp
.
Solution
class Router {
int capacity;
queue<long long> q;
set<long long> packets;
map<int, vector<int>> dest2packets;
const long long BASE = 3e5;
const long long ROUTEBASE = 1 << 20;
constexpr long long getId(int source, int destination, int timestamp) {
return (source * BASE + destination) * ROUTEBASE + timestamp;
}
vector<int> getFront() {
long long id = q.front();
return {int(id / ROUTEBASE / BASE), int(id / ROUTEBASE % BASE), int(id % ROUTEBASE)};
}
void popFront() {
long long id = q.front();
int dest = id / ROUTEBASE % BASE;
q.pop();
packets.erase(id);
dest2packets[dest].erase(dest2packets[dest].begin());
}
public:
Router(int memoryLimit): capacity(memoryLimit) { }
bool addPacket(int source, int destination, int timestamp) {
long long id = getId(source, destination, timestamp);
if(packets.count(id)) return false;
if(q.size() == capacity) popFront();
q.push(id);
packets.insert(id);
dest2packets[destination].push_back(timestamp);
return true;
}
vector<int> forwardPacket() {
if(q.empty()) return {};
auto packet = getFront();
popFront();
return packet;
}
int getCount(int destination, int startTime, int endTime) {
if(!dest2packets.count(destination)) return 0;
auto &container = dest2packets[destination];
auto begin = lower_bound(container.begin(), container.end(), startTime) - container.begin();
auto end = upper_bound(container.begin(), container.end(), endTime) - container.begin();
return end - begin;
}
};
// Accepted
// 751/751 cases passed (206 ms)
// Your runtime beats 83.45 % of cpp submissions
// Your memory usage beats 98.31 % of cpp submissions (414.6 MB)