3508. 设计路由器
请你设计一个数据结构来高效管理网络路由器中的数据包。每个数据包包含以下属性:
source
:生成该数据包的机器的唯一标识符。destination
:目标机器的唯一标识符。timestamp
:该数据包到达路由器的时间戳。实现 Router
类:
Router(int memoryLimit)
:初始化路由器对象,并设置固定的内存限制。
memoryLimit
是路由器在任意时间点可以存储的 最大 数据包数量。bool addPacket(int source, int destination, int timestamp)
:将具有给定属性的数据包添加到路由器。
source
、destination
和 timestamp
的数据包,则视为重复数据包。true
;否则返回 false
。int[] forwardPacket()
:以 FIFO(先进先出)顺序转发下一个数据包。
[source, destination, timestamp]
的形式返回该数据包。int getCount(int destination, int startTime, int endTime)
:
destination
且时间戳在范围 [startTime, endTime]
(包括两端)内的数据包数量。注意:对于 addPacket
的查询会按照 timestamp
的递增顺序进行。
示例 1:
输入:
["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]]
输出:
[null, true, true, false, true, true, [2, 5, 90], true, 1]
解释:
Router router = new Router(3);
// 初始化路由器,内存限制为 3。router.addPacket(1, 4, 90);
// 数据包被添加,返回 True。router.addPacket(2, 5, 90);
// 数据包被添加,返回 True。router.addPacket(1, 4, 90);
// 这是一个重复数据包,返回 False。router.addPacket(3, 5, 95);
// 数据包被添加,返回 True。router.addPacket(4, 5, 105);
// 数据包被添加,[1, 4, 90]
被移除,因为数据包数量超过限制,返回 True。router.forwardPacket();
// 转发数据包 [2, 5, 90]
并将其从路由器中移除。router.addPacket(5, 2, 110);
// 数据包被添加,返回 True。router.getCount(5, 100, 110);
// 唯一目标地址为 5 且时间在 [100, 110]
范围内的数据包是 [4, 5, 105]
,返回 1。示例 2:
输入:
["Router", "addPacket", "forwardPacket", "forwardPacket"]
[[2], [7, 4, 90], [], []]
输出:
[null, true, [7, 4, 90], []]
解释:
Router router = new Router(2);
// 初始化路由器,内存限制为 2。router.addPacket(7, 4, 90);
// 返回 True。router.forwardPacket();
// 返回 [7, 4, 90]
。router.forwardPacket();
// 没有数据包可以转发,返回 []
。
提示:
2 <= memoryLimit <= 105
1 <= source, destination <= 2 * 105
1 <= timestamp <= 109
1 <= startTime <= endTime <= 109
addPacket
、forwardPacket
和 getCount
方法的总调用次数最多为 105
。addPacket
的查询,timestamp
按递增顺序给出。原站题解
java 解法, 执行用时: 473 ms, 内存消耗: 150.7 MB, 提交时间: 2025-04-07 09:36:45
class Router { private Map<Integer, List<int[]>> routerMap = new HashMap<>(); private List<int[]> routerList = new ArrayList<>(); int limit; Set<String> routerSet = new HashSet<>(); public Router(int memoryLimit) { this.limit = memoryLimit; } public boolean addPacket(int source, int destination, int timestamp) { int[] data = {source, destination, timestamp}; String hash = hash(data); if (routerSet.contains(hash)) { return false; } if (routerList.size() == limit) { forwardPacket(); } routerSet.add(hash); routerList.add(data); routerMap.computeIfAbsent(destination, k -> new ArrayList<>()).add(data); return true; } public int[] forwardPacket() { if (routerList.isEmpty()) { return new int[]{}; } int[] data = routerList.remove(0); routerSet.remove(hash(data)); List<int[]> mapData = routerMap.get(data[1]); mapData.remove(0); return data; } public int getCount(int destination, int startTime, int endTime) { List<int[]> dataList = routerMap.get(destination); if (startTime > endTime || dataList == null || dataList.isEmpty()) { return 0; } int l = binSearchLeft(dataList, startTime); int r = binSearchRight(dataList, endTime); if (l == -1 || r == -1) { return 0; } return Math.max(r - l + 1, 0); } private int binSearchLeft(List<int[]> dataList, int timestamp) { int l = 0, r = dataList.size() - 1, res = -1; while (l <= r) { int mid = l + (r - l) / 2; int t = dataList.get(mid)[2]; if (timestamp <= t) { res = mid; r = mid - 1; } else { l = mid + 1; } } return res; } private int binSearchRight(List<int[]> dataList, int timestamp) { int l = 0, r = dataList.size() - 1, res = -1; while (l <= r) { int mid = l + (r - l) / 2; int t = dataList.get(mid)[2]; if (timestamp >= t) { res = mid; l = mid + 1; } else { r = mid - 1; } } return res; } private String hash(int[] nums) { return String.format("%s-%s-%s", nums[0], nums[1], nums[2]); } } /** * Your Router object will be instantiated and called as such: * Router obj = new Router(memoryLimit); * boolean param_1 = obj.addPacket(source,destination,timestamp); * int[] param_2 = obj.forwardPacket(); * int param_3 = obj.getCount(destination,startTime,endTime); */
cpp 解法, 执行用时: 243 ms, 内存消耗: 412.8 MB, 提交时间: 2025-04-07 09:35:26
class Router { int mxsize; queue<tuple<int, int, int>> q; //进出顺序 set<tuple<int, int, int>> set; //去重 unordered_map<int, vector<int> > map; //查询timestamp public: Router(int memoryLimit) :mxsize(memoryLimit) { } bool addPacket(int source, int destination, int timestamp) { tuple<int, int, int> t(source, destination,timestamp); if (set.count(t)) { return false; } q.push(t); set.insert(t); map[destination].emplace_back(timestamp); if (q.size() > mxsize) { //大于最大size,直接调用forwardPacket出队一个元素 forwardPacket(); } return true; } vector<int> forwardPacket() { if (q.empty()) { return {}; } auto t = q.front(); set.erase(set.find(t)); auto& pairs = map[get<1>(t)]; auto p = ranges::lower_bound(pairs, get<2>(t)); pairs.erase(p); q.pop(); return { get<0>(t),get<1>(t), get<2>(t)}; } int getCount(int destination, int startTime, int endTime) { auto& pairs = map[destination]; auto s = ranges::lower_bound(pairs, startTime); auto e = ranges::upper_bound(pairs, endTime); return e - s; } }; /** * 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); */
python3 解法, 执行用时: 372 ms, 内存消耗: 105.9 MB, 提交时间: 2025-04-07 09:34:05
from bisect import bisect_left, bisect_right from collections import deque, defaultdict from typing import List class Router: def __init__(self, memoryLimit: int): self.memoryLimit = memoryLimit self.sl = deque() self.record_destination = defaultdict(deque) self.vis = set() def addPacket(self, source: int, destination: int, timestamp: int) -> bool: comb = (timestamp, source, destination) if comb in self.vis: return False self.vis.add(comb) if len(self.sl) == self.memoryLimit: self.forwardPacket() self.sl.append(comb) self.record_destination[destination].append(timestamp) return True def forwardPacket(self) -> List[int]: if not self.sl: return [] timestamp, source, destination = self.sl.popleft() self.record_destination[destination].popleft() self.vis.remove((timestamp, source, destination)) return [source, destination, timestamp] def getCount(self, destination: int, startTime: int, endTime: int) -> int: nums = self.record_destination[destination] left = bisect_left(nums, startTime) # nums[left] >= startTime right = bisect_right(nums, endTime) - 1 # nums[right] <= endTime return right - left + 1 # 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) # ©leetcode
python3 解法, 执行用时: 444 ms, 内存消耗: 102.7 MB, 提交时间: 2025-04-07 09:33:34
from sortedcontainers import SortedList mx = int(1e9) class Router: def __init__(self, memoryLimit: int): # 双端队列,FIFO self.que = deque() # keyw为 destination 的时间有序集合,用于查找时间范围内的包数目 self.dt = defaultdict(lambda :SortedList()) self.n = memoryLimit self.A = set() def addPacket(self, source: int, destination: int, timestamp: int) -> bool: key = (source,destination,timestamp) if key in self.A: return False self.que.append(key) self.A.add(key) self.dt[destination].add((timestamp,source)) if len(self.que) > self.n: a,b,c = self.que.popleft() self.A.remove((a,b,c)) idx = self.dt[b].bisect_left((c,a)) del self.dt[b][idx] return True def forwardPacket(self) -> List[int]: if not self.que: return [] res = self.que.popleft() source,destination,timestamp = res idx = self.dt[destination].bisect_left((timestamp,source)) del self.dt[destination][idx] self.A.remove(res) return res def getCount(self, destination: int, startTime: int, endTime: int) -> int: sl = self.dt[destination] return sl.bisect_right((endTime,mx)) - sl.bisect_right((startTime-1,mx)) # 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)
上一题