LeetCode Problem Workspace
Implement Router
Efficiently design a Router class to manage network packets with memory limits using array scanning and hash lookups.
6
Topics
6
Code langs
3
Related
Practice Focus
Medium · Array scanning plus hash lookup
Answer-first summary
Efficiently design a Router class to manage network packets with memory limits using array scanning and hash lookups.
Ace coding interviews with Interview AiBoxInterview AiBox guidance for Array scanning plus hash lookup
This problem requires implementing a Router that stores packets and processes them efficiently under a memory limit. Use array scanning for ordered packet management and a hash map for quick lookups by source and destination. Handling duplicates and memory constraints correctly ensures accurate packet forwarding and counting.
Problem Statement
Design a Router class that simulates network packet management under a fixed memory limit. Each packet has a source, destination, and timestamp. The Router must efficiently add packets, forward packets in memory order, and count active packets within a time window. Duplicate packets exceeding the memory limit should be rejected.
Implement the following operations: Router(int memoryLimit) to initialize the router, addPacket(source, destination, timestamp) to store a packet respecting memory limits, forwardPacket() to send the earliest packet and remove it from memory, and getCount(startTime, endTime) to return the number of packets within a timestamp range. Ensure all operations are optimized using array scanning combined with hash lookups.
Examples
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
Example details omitted.
Example 2
Input: ["Router", "addPacket", "forwardPacket", "forwardPacket"] [[2], [7, 4, 90], [], []]
Output: [null, true, [7, 4, 90], []] Explanation
Example details omitted.
Constraints
- 2 <= memoryLimit <= 105
- 1 <= source, destination <= 2 * 105
- 1 <= timestamp <= 109
- 1 <= startTime <= endTime <= 109
- At most 105 calls will be made to addPacket, forwardPacket, and getCount methods altogether.
- queries for addPacket will be made in increasing order of timestamp.
Solution Approach
Use deque for ordered packet storage
Store packets in a deque to maintain the order they arrive, enabling O(1) removal from the front for forwarding. This avoids costly shifting of array elements and aligns with the problem pattern of array scanning.
Use hash map for duplicate detection
Maintain a hash map keyed by (source, destination) pairs to quickly detect duplicates before insertion. This ensures addPacket operations respect memory limits and supports constant-time lookup, directly addressing the hash lookup pattern.
Implement range count with binary search
Keep packets sorted by timestamp and use binary search to count packets within a time range for getCount. This leverages the array scanning plus hash lookup pattern to efficiently retrieve counts without scanning all packets.
Complexity Analysis
| Metric | Value |
|---|---|
| Time | Depends on the final approach |
| Space | Depends on the final approach |
Time complexity: addPacket and forwardPacket are O(1) amortized due to deque and hash map usage; getCount is O(log n) for binary search over timestamps. Space complexity: O(n) for storing packets in deque and hash map.
What Interviewers Usually Probe
- Ask about handling memory limits when adding duplicate packets.
- Check if forwarding maintains correct packet order under constraints.
- Probe for efficient counting of packets within timestamp ranges.
Common Pitfalls or Variants
Common pitfalls
- Not removing packets from the hash map when forwarding, causing false duplicates.
- Scanning the entire array for counts instead of using binary search.
- Failing to respect memory limits, leading to incorrect addPacket results.
Follow-up variants
- Router with priority-based packet forwarding instead of FIFO order.
- Router supporting dynamic memory resizing with the same addPacket logic.
- Router allowing bulk forwarding of multiple packets in one operation.
FAQ
What is the main pattern used in Implement Router problem?
The key pattern is array scanning combined with hash lookup, allowing efficient packet ordering and duplicate detection.
How do I handle memory limits when adding packets?
Use a deque to store packets and a hash map for lookups; reject new packets if memory is full, maintaining consistent memory tracking.
Can getCount be optimized instead of scanning all packets?
Yes, keep packets sorted by timestamp and use binary search to find the range, which avoids scanning the entire array.
Why is deque preferred over array for packet storage?
Deque allows O(1) insertion at the back and removal from the front, matching FIFO forwarding without shifting elements.
What common mistakes occur in Implement Router?
Forgetting to update the hash map on forwarding, scanning linearly for counts, or exceeding memory limits are frequent errors.
Solution
Solution 1: Hash Map + Queue + Binary Search
We use a hash map $\textit{vis}$ to store the hash values of packets that have already been added, a queue $\textit{q}$ to store the packets currently in the router, a hash map $\textit{idx}$ to record the number of packets already forwarded for each destination, and a hash map $\textit{d}$ to store the list of timestamps for each destination.
class Router:
def __init__(self, memoryLimit: int):
self.lim = memoryLimit
self.vis = set()
self.q = deque()
self.idx = defaultdict(int)
self.d = defaultdict(list)
def addPacket(self, source: int, destination: int, timestamp: int) -> bool:
x = self.f(source, destination, timestamp)
if x in self.vis:
return False
self.vis.add(x)
if len(self.q) >= self.lim:
self.forwardPacket()
self.q.append((source, destination, timestamp))
self.d[destination].append(timestamp)
return True
def forwardPacket(self) -> List[int]:
if not self.q:
return []
s, d, t = self.q.popleft()
self.vis.remove(self.f(s, d, t))
self.idx[d] += 1
return [s, d, t]
def f(self, a: int, b: int, c: int) -> int:
return a << 46 | b << 29 | c
def getCount(self, destination: int, startTime: int, endTime: int) -> int:
ls = self.d[destination]
k = self.idx[destination]
i = bisect_left(ls, startTime, k)
j = bisect_left(ls, endTime + 1, k)
return j - i
# Your Router object will be instantiated and called as such:
# obj = Router(memoryLimit)
# param_1 = obj.addPacket(source,destination,timestamp)
# param_2 = obj.forwardPacket()
# param_3 = obj.getCount(destination,startTime,endTime)Continue Topic
array
Practice more edge cases under the same topic.
arrow_forwardauto_awesomeContinue Pattern
Array scanning plus hash lookup
Expand the same solving frame across more problems.
arrow_forwardsignal_cellular_altSame Difficulty Track
Medium
Stay on this level to stabilize interview delivery.
arrow_forward