From 518f7cd437b9c0a28fe112037e0741eb71953f44 Mon Sep 17 00:00:00 2001 From: Libin YANG Date: Sat, 20 Sep 2025 20:23:03 +0800 Subject: [PATCH] feat: add solutions to lc problem: No.3508 --- .../3500-3599/3508.Implement Router/README.md | 396 +++++++++++++++++- .../3508.Implement Router/README_EN.md | 396 +++++++++++++++++- .../3508.Implement Router/Solution.cpp | 59 +++ .../3508.Implement Router/Solution.go | 63 +++ .../3508.Implement Router/Solution.java | 69 +++ .../3508.Implement Router/Solution.py | 44 ++ .../3508.Implement Router/Solution.rs | 61 +++ .../3508.Implement Router/Solution.ts | 76 ++++ 8 files changed, 1156 insertions(+), 8 deletions(-) create mode 100644 solution/3500-3599/3508.Implement Router/Solution.cpp create mode 100644 solution/3500-3599/3508.Implement Router/Solution.go create mode 100644 solution/3500-3599/3508.Implement Router/Solution.java create mode 100644 solution/3500-3599/3508.Implement Router/Solution.py create mode 100644 solution/3500-3599/3508.Implement Router/Solution.rs create mode 100644 solution/3500-3599/3508.Implement Router/Solution.ts diff --git a/solution/3500-3599/3508.Implement Router/README.md b/solution/3500-3599/3508.Implement Router/README.md index 1e70b3ae14a38..c53033d3559b2 100644 --- a/solution/3500-3599/3508.Implement Router/README.md +++ b/solution/3500-3599/3508.Implement Router/README.md @@ -121,32 +121,420 @@ tags: -### 方法一 +### 方法一: 哈希表 + 队列 + 二分查找 + +我们用一个哈希表 $\textit{vis}$ 来存储已经添加过的数据包的哈希值,用一个队列 $\textit{q}$ 来存储当前路由器中的数据包,用一个哈希表 $\textit{idx}$ 来记录每个目标地址已经转发的数据包数量,用一个哈希表 $\textit{d}$ 来存储每个目标地址对应的时间戳列表。 + +对于 $\textit{addPacket}$ 方法,我们计算数据包的哈希值,如果已经存在于 $\textit{vis}$ 中,则返回 $\text{false}$;否则将其添加到 $\textit{vis}$ 中,并检查当前队列的大小是否超过内存限制,如果超过则调用 $\textit{forwardPacket}$ 方法移除最旧的数据包,然后将新数据包添加到队列中,并将时间戳添加到对应目标地址的时间戳列表中,最后返回 $\text{true}$。时间复杂度为 $O(1)$。 + +对于 $\textit{forwardPacket}$ 方法,如果队列为空则返回空数组;否则移除队列头部的数据包,并从 $\textit{vis}$ 中删除其哈希值,更新对应目标地址的已转发数据包数量,最后返回该数据包。时间复杂度为 $O(1)$。 + +对于 $\textit{getCount}$ 方法,我们获取对应目标地址的时间戳列表和已转发数据包数量,然后使用二分查找找到时间戳在指定范围内的数量,最后返回该数量。时间复杂度为 $O(\log n)$,其中 $n$ 是时间戳列表的长度。 + +空间复杂度 $O(n)$。 #### Python3 ```python - +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) ``` #### Java ```java - +class Router { + private int lim; + private Set vis = new HashSet<>(); + private Deque q = new ArrayDeque<>(); + private Map idx = new HashMap<>(); + private Map> d = new HashMap<>(); + + public Router(int memoryLimit) { + this.lim = memoryLimit; + } + + public boolean addPacket(int source, int destination, int timestamp) { + long x = f(source, destination, timestamp); + if (vis.contains(x)) { + return false; + } + vis.add(x); + if (q.size() >= lim) { + forwardPacket(); + } + q.offer(new int[] {source, destination, timestamp}); + d.computeIfAbsent(destination, k -> new ArrayList<>()).add(timestamp); + return true; + } + + public int[] forwardPacket() { + if (q.isEmpty()) { + return new int[] {}; + } + int[] packet = q.poll(); + int s = packet[0], d_ = packet[1], t = packet[2]; + vis.remove(f(s, d_, t)); + idx.merge(d_, 1, Integer::sum); + return new int[] {s, d_, t}; + } + + private long f(int a, int b, int c) { + return ((long) a << 46) | ((long) b << 29) | (long) c; + } + + public int getCount(int destination, int startTime, int endTime) { + List ls = d.getOrDefault(destination, List.of()); + int k = idx.getOrDefault(destination, 0); + int i = lowerBound(ls, startTime, k); + int j = lowerBound(ls, endTime + 1, k); + return j - i; + } + + private int lowerBound(List list, int target, int fromIndex) { + int l = fromIndex, r = list.size(); + while (l < r) { + int m = (l + r) >>> 1; + if (list.get(m) < target) { + l = m + 1; + } else { + r = m; + } + } + return l; + } +} + +/** + * 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); + */ ``` #### C++ ```cpp - +class Router { +private: + int lim; + unordered_set vis; + deque> q; + unordered_map idx; + unordered_map> d; + + long long f(int a, int b, int c) { + return ((long long) a << 46) | ((long long) b << 29) | (long long) c; + } + +public: + Router(int memoryLimit) { + lim = memoryLimit; + } + + bool addPacket(int source, int destination, int timestamp) { + long long x = f(source, destination, timestamp); + if (vis.count(x)) { + return false; + } + vis.insert(x); + if ((int) q.size() >= lim) { + forwardPacket(); + } + q.push_back({source, destination, timestamp}); + d[destination].push_back(timestamp); + return true; + } + + vector forwardPacket() { + if (q.empty()) { + return {}; + } + auto packet = q.front(); + q.pop_front(); + int s = packet[0], d_ = packet[1], t = packet[2]; + vis.erase(f(s, d_, t)); + idx[d_]++; + return {s, d_, t}; + } + + int getCount(int destination, int startTime, int endTime) { + auto& ls = d[destination]; + int k = idx[destination]; + auto i = lower_bound(ls.begin() + k, ls.end(), startTime); + auto j = lower_bound(ls.begin() + k, ls.end(), endTime + 1); + return j - i; + } +}; + +/** + * Your Router object will be instantiated and called as such: + * Router* obj = new Router(memoryLimit); + * bool param_1 = obj->addPacket(source,destination,timestamp); + * vector param_2 = obj->forwardPacket(); + * int param_3 = obj->getCount(destination,startTime,endTime); + */ ``` #### Go ```go +type Router struct { + lim int + vis map[int64]struct{} + q [][3]int + idx map[int]int + d map[int][]int +} + +func Constructor(memoryLimit int) Router { + return Router{ + lim: memoryLimit, + vis: make(map[int64]struct{}), + q: make([][3]int, 0), + idx: make(map[int]int), + d: make(map[int][]int), + } +} + +func (this *Router) f(a, b, c int) int64 { + return int64(a)<<46 | int64(b)<<29 | int64(c) +} + +func (this *Router) AddPacket(source int, destination int, timestamp int) bool { + x := this.f(source, destination, timestamp) + if _, ok := this.vis[x]; ok { + return false + } + this.vis[x] = struct{}{} + if len(this.q) >= this.lim { + this.ForwardPacket() + } + this.q = append(this.q, [3]int{source, destination, timestamp}) + this.d[destination] = append(this.d[destination], timestamp) + return true +} + +func (this *Router) ForwardPacket() []int { + if len(this.q) == 0 { + return []int{} + } + packet := this.q[0] + this.q = this.q[1:] + s, d, t := packet[0], packet[1], packet[2] + delete(this.vis, this.f(s, d, t)) + this.idx[d]++ + return []int{s, d, t} +} + +func (this *Router) GetCount(destination int, startTime int, endTime int) int { + ls := this.d[destination] + k := this.idx[destination] + i := sort.Search(len(ls)-k, func(i int) bool { return ls[i+k] >= startTime }) + k + j := sort.Search(len(ls)-k, func(i int) bool { return ls[i+k] >= endTime+1 }) + k + return j - i +} + +/** + * Your Router object will be instantiated and called as such: + * obj := Constructor(memoryLimit) + * param_1 := obj.AddPacket(source,destination,timestamp) + * param_2 := obj.ForwardPacket() + * param_3 := obj.GetCount(destination,startTime,endTime) + */ +``` + +#### TypeScript + +```ts +class Router { + private lim: number; + private vis: Set; + private q: [number, number, number][]; + private idx: Map; + private d: Map; + + constructor(memoryLimit: number) { + this.lim = memoryLimit; + this.vis = new Set(); + this.q = []; + this.idx = new Map(); + this.d = new Map(); + } + + private f(a: number, b: number, c: number): number { + return ((BigInt(a) << 46n) | (BigInt(b) << 29n) | BigInt(c)) as unknown as number; + } + + addPacket(source: number, destination: number, timestamp: number): boolean { + const x = this.f(source, destination, timestamp); + if (this.vis.has(x)) { + return false; + } + this.vis.add(x); + if (this.q.length >= this.lim) { + this.forwardPacket(); + } + this.q.push([source, destination, timestamp]); + if (!this.d.has(destination)) { + this.d.set(destination, []); + } + this.d.get(destination)!.push(timestamp); + return true; + } + + forwardPacket(): number[] { + if (this.q.length === 0) { + return []; + } + const [s, d, t] = this.q.shift()!; + this.vis.delete(this.f(s, d, t)); + this.idx.set(d, (this.idx.get(d) ?? 0) + 1); + return [s, d, t]; + } + + getCount(destination: number, startTime: number, endTime: number): number { + const ls = this.d.get(destination) ?? []; + const k = this.idx.get(destination) ?? 0; + const i = this.lowerBound(ls, startTime, k); + const j = this.lowerBound(ls, endTime + 1, k); + return j - i; + } + + private lowerBound(arr: number[], target: number, from: number): number { + let l = from, + r = arr.length; + while (l < r) { + const m = Math.floor((l + r) / 2); + if (arr[m] < target) { + l = m + 1; + } else { + r = m; + } + } + return l; + } +} + +/** + * Your Router object will be instantiated and called as such: + * var obj = new Router(memoryLimit) + * var param_1 = obj.addPacket(source,destination,timestamp) + * var param_2 = obj.forwardPacket() + * var param_3 = obj.getCount(destination,startTime,endTime) + */ +``` +#### Rust + +```rust +use std::collections::{HashSet, HashMap, VecDeque}; + +struct Router { + lim: usize, + vis: HashSet, + q: VecDeque<(i32, i32, i32)>, + idx: HashMap, + d: HashMap>, +} + +impl Router { + fn new(memory_limit: i32) -> Self { + Router { + lim: memory_limit as usize, + vis: HashSet::new(), + q: VecDeque::new(), + idx: HashMap::new(), + d: HashMap::new(), + } + } + + fn f(a: i32, b: i32, c: i32) -> i64 { + ((a as i64) << 46) | ((b as i64) << 29) | (c as i64) + } + + fn add_packet(&mut self, source: i32, destination: i32, timestamp: i32) -> bool { + let x = Self::f(source, destination, timestamp); + if self.vis.contains(&x) { + return false; + } + self.vis.insert(x); + if self.q.len() >= self.lim { + self.forward_packet(); + } + self.q.push_back((source, destination, timestamp)); + self.d.entry(destination).or_default().push(timestamp); + true + } + + fn forward_packet(&mut self) -> Vec { + if let Some((s, d, t)) = self.q.pop_front() { + self.vis.remove(&Self::f(s, d, t)); + *self.idx.entry(d).or_insert(0) += 1; + vec![s, d, t] + } else { + vec![] + } + } + + fn get_count(&self, destination: i32, start_time: i32, end_time: i32) -> i32 { + let ls = self.d.get(&destination); + if ls.is_none() { + return 0; + } + let ls = ls.unwrap(); + let k = *self.idx.get(&destination).unwrap_or(&0); + let i = k + ls[k..].partition_point(|&x| x < start_time); + let j = k + ls[k..].partition_point(|&x| x < end_time + 1); + (j - i) as i32 + } +} ``` diff --git a/solution/3500-3599/3508.Implement Router/README_EN.md b/solution/3500-3599/3508.Implement Router/README_EN.md index abd75285c5ec5..c14c0cf894a8e 100644 --- a/solution/3500-3599/3508.Implement Router/README_EN.md +++ b/solution/3500-3599/3508.Implement Router/README_EN.md @@ -119,32 +119,420 @@ router.forwardPacket(); // There are no packets left, return []. -### Solution 1 +### 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. + +For the $\textit{addPacket}$ method, we compute the hash value of the packet. If it already exists in $\textit{vis}$, we return $\text{false}$; otherwise, we add it to $\textit{vis}$, check if the current queue size exceeds the memory limit, and if so, call the $\textit{forwardPacket}$ method to remove the oldest packet. Then, we add the new packet to the queue and append its timestamp to the corresponding destination's timestamp list, finally returning $\text{true}$. The time complexity is $O(1)$. + +For the $\textit{forwardPacket}$ method, if the queue is empty, we return an empty array; otherwise, we remove the packet at the head of the queue, delete its hash value from $\textit{vis}$, update the number of forwarded packets for the corresponding destination, and return the packet. The time complexity is $O(1)$. + +For the $\textit{getCount}$ method, we get the timestamp list and the number of forwarded packets for the given destination, then use binary search to find the number of timestamps within the specified range, and return that count. The time complexity is $O(\log n)$, where $n$ is the length of the timestamp list. + +The space complexity is $O(n)$. #### Python3 ```python - +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) ``` #### Java ```java - +class Router { + private int lim; + private Set vis = new HashSet<>(); + private Deque q = new ArrayDeque<>(); + private Map idx = new HashMap<>(); + private Map> d = new HashMap<>(); + + public Router(int memoryLimit) { + this.lim = memoryLimit; + } + + public boolean addPacket(int source, int destination, int timestamp) { + long x = f(source, destination, timestamp); + if (vis.contains(x)) { + return false; + } + vis.add(x); + if (q.size() >= lim) { + forwardPacket(); + } + q.offer(new int[] {source, destination, timestamp}); + d.computeIfAbsent(destination, k -> new ArrayList<>()).add(timestamp); + return true; + } + + public int[] forwardPacket() { + if (q.isEmpty()) { + return new int[] {}; + } + int[] packet = q.poll(); + int s = packet[0], d_ = packet[1], t = packet[2]; + vis.remove(f(s, d_, t)); + idx.merge(d_, 1, Integer::sum); + return new int[] {s, d_, t}; + } + + private long f(int a, int b, int c) { + return ((long) a << 46) | ((long) b << 29) | (long) c; + } + + public int getCount(int destination, int startTime, int endTime) { + List ls = d.getOrDefault(destination, List.of()); + int k = idx.getOrDefault(destination, 0); + int i = lowerBound(ls, startTime, k); + int j = lowerBound(ls, endTime + 1, k); + return j - i; + } + + private int lowerBound(List list, int target, int fromIndex) { + int l = fromIndex, r = list.size(); + while (l < r) { + int m = (l + r) >>> 1; + if (list.get(m) < target) { + l = m + 1; + } else { + r = m; + } + } + return l; + } +} + +/** + * 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); + */ ``` #### C++ ```cpp - +class Router { +private: + int lim; + unordered_set vis; + deque> q; + unordered_map idx; + unordered_map> d; + + long long f(int a, int b, int c) { + return ((long long) a << 46) | ((long long) b << 29) | (long long) c; + } + +public: + Router(int memoryLimit) { + lim = memoryLimit; + } + + bool addPacket(int source, int destination, int timestamp) { + long long x = f(source, destination, timestamp); + if (vis.count(x)) { + return false; + } + vis.insert(x); + if ((int) q.size() >= lim) { + forwardPacket(); + } + q.push_back({source, destination, timestamp}); + d[destination].push_back(timestamp); + return true; + } + + vector forwardPacket() { + if (q.empty()) { + return {}; + } + auto packet = q.front(); + q.pop_front(); + int s = packet[0], d_ = packet[1], t = packet[2]; + vis.erase(f(s, d_, t)); + idx[d_]++; + return {s, d_, t}; + } + + int getCount(int destination, int startTime, int endTime) { + auto& ls = d[destination]; + int k = idx[destination]; + auto i = lower_bound(ls.begin() + k, ls.end(), startTime); + auto j = lower_bound(ls.begin() + k, ls.end(), endTime + 1); + return j - i; + } +}; + +/** + * Your Router object will be instantiated and called as such: + * Router* obj = new Router(memoryLimit); + * bool param_1 = obj->addPacket(source,destination,timestamp); + * vector param_2 = obj->forwardPacket(); + * int param_3 = obj->getCount(destination,startTime,endTime); + */ ``` #### Go ```go +type Router struct { + lim int + vis map[int64]struct{} + q [][3]int + idx map[int]int + d map[int][]int +} + +func Constructor(memoryLimit int) Router { + return Router{ + lim: memoryLimit, + vis: make(map[int64]struct{}), + q: make([][3]int, 0), + idx: make(map[int]int), + d: make(map[int][]int), + } +} + +func (this *Router) f(a, b, c int) int64 { + return int64(a)<<46 | int64(b)<<29 | int64(c) +} + +func (this *Router) AddPacket(source int, destination int, timestamp int) bool { + x := this.f(source, destination, timestamp) + if _, ok := this.vis[x]; ok { + return false + } + this.vis[x] = struct{}{} + if len(this.q) >= this.lim { + this.ForwardPacket() + } + this.q = append(this.q, [3]int{source, destination, timestamp}) + this.d[destination] = append(this.d[destination], timestamp) + return true +} + +func (this *Router) ForwardPacket() []int { + if len(this.q) == 0 { + return []int{} + } + packet := this.q[0] + this.q = this.q[1:] + s, d, t := packet[0], packet[1], packet[2] + delete(this.vis, this.f(s, d, t)) + this.idx[d]++ + return []int{s, d, t} +} + +func (this *Router) GetCount(destination int, startTime int, endTime int) int { + ls := this.d[destination] + k := this.idx[destination] + i := sort.Search(len(ls)-k, func(i int) bool { return ls[i+k] >= startTime }) + k + j := sort.Search(len(ls)-k, func(i int) bool { return ls[i+k] >= endTime+1 }) + k + return j - i +} + +/** + * Your Router object will be instantiated and called as such: + * obj := Constructor(memoryLimit) + * param_1 := obj.AddPacket(source,destination,timestamp) + * param_2 := obj.ForwardPacket() + * param_3 := obj.GetCount(destination,startTime,endTime) + */ +``` + +#### TypeScript + +```ts +class Router { + private lim: number; + private vis: Set; + private q: [number, number, number][]; + private idx: Map; + private d: Map; + + constructor(memoryLimit: number) { + this.lim = memoryLimit; + this.vis = new Set(); + this.q = []; + this.idx = new Map(); + this.d = new Map(); + } + + private f(a: number, b: number, c: number): number { + return ((BigInt(a) << 46n) | (BigInt(b) << 29n) | BigInt(c)) as unknown as number; + } + + addPacket(source: number, destination: number, timestamp: number): boolean { + const x = this.f(source, destination, timestamp); + if (this.vis.has(x)) { + return false; + } + this.vis.add(x); + if (this.q.length >= this.lim) { + this.forwardPacket(); + } + this.q.push([source, destination, timestamp]); + if (!this.d.has(destination)) { + this.d.set(destination, []); + } + this.d.get(destination)!.push(timestamp); + return true; + } + + forwardPacket(): number[] { + if (this.q.length === 0) { + return []; + } + const [s, d, t] = this.q.shift()!; + this.vis.delete(this.f(s, d, t)); + this.idx.set(d, (this.idx.get(d) ?? 0) + 1); + return [s, d, t]; + } + + getCount(destination: number, startTime: number, endTime: number): number { + const ls = this.d.get(destination) ?? []; + const k = this.idx.get(destination) ?? 0; + const i = this.lowerBound(ls, startTime, k); + const j = this.lowerBound(ls, endTime + 1, k); + return j - i; + } + + private lowerBound(arr: number[], target: number, from: number): number { + let l = from, + r = arr.length; + while (l < r) { + const m = Math.floor((l + r) / 2); + if (arr[m] < target) { + l = m + 1; + } else { + r = m; + } + } + return l; + } +} + +/** + * Your Router object will be instantiated and called as such: + * var obj = new Router(memoryLimit) + * var param_1 = obj.addPacket(source,destination,timestamp) + * var param_2 = obj.forwardPacket() + * var param_3 = obj.getCount(destination,startTime,endTime) + */ +``` +#### Rust + +```rust +use std::collections::{HashSet, HashMap, VecDeque}; + +struct Router { + lim: usize, + vis: HashSet, + q: VecDeque<(i32, i32, i32)>, + idx: HashMap, + d: HashMap>, +} + +impl Router { + fn new(memory_limit: i32) -> Self { + Router { + lim: memory_limit as usize, + vis: HashSet::new(), + q: VecDeque::new(), + idx: HashMap::new(), + d: HashMap::new(), + } + } + + fn f(a: i32, b: i32, c: i32) -> i64 { + ((a as i64) << 46) | ((b as i64) << 29) | (c as i64) + } + + fn add_packet(&mut self, source: i32, destination: i32, timestamp: i32) -> bool { + let x = Self::f(source, destination, timestamp); + if self.vis.contains(&x) { + return false; + } + self.vis.insert(x); + if self.q.len() >= self.lim { + self.forward_packet(); + } + self.q.push_back((source, destination, timestamp)); + self.d.entry(destination).or_default().push(timestamp); + true + } + + fn forward_packet(&mut self) -> Vec { + if let Some((s, d, t)) = self.q.pop_front() { + self.vis.remove(&Self::f(s, d, t)); + *self.idx.entry(d).or_insert(0) += 1; + vec![s, d, t] + } else { + vec![] + } + } + + fn get_count(&self, destination: i32, start_time: i32, end_time: i32) -> i32 { + let ls = self.d.get(&destination); + if ls.is_none() { + return 0; + } + let ls = ls.unwrap(); + let k = *self.idx.get(&destination).unwrap_or(&0); + let i = k + ls[k..].partition_point(|&x| x < start_time); + let j = k + ls[k..].partition_point(|&x| x < end_time + 1); + (j - i) as i32 + } +} ``` diff --git a/solution/3500-3599/3508.Implement Router/Solution.cpp b/solution/3500-3599/3508.Implement Router/Solution.cpp new file mode 100644 index 0000000000000..d5a286f0b89a5 --- /dev/null +++ b/solution/3500-3599/3508.Implement Router/Solution.cpp @@ -0,0 +1,59 @@ +class Router { +private: + int lim; + unordered_set vis; + deque> q; + unordered_map idx; + unordered_map> d; + + long long f(int a, int b, int c) { + return ((long long) a << 46) | ((long long) b << 29) | (long long) c; + } + +public: + Router(int memoryLimit) { + lim = memoryLimit; + } + + bool addPacket(int source, int destination, int timestamp) { + long long x = f(source, destination, timestamp); + if (vis.count(x)) { + return false; + } + vis.insert(x); + if ((int) q.size() >= lim) { + forwardPacket(); + } + q.push_back({source, destination, timestamp}); + d[destination].push_back(timestamp); + return true; + } + + vector forwardPacket() { + if (q.empty()) { + return {}; + } + auto packet = q.front(); + q.pop_front(); + int s = packet[0], d_ = packet[1], t = packet[2]; + vis.erase(f(s, d_, t)); + idx[d_]++; + return {s, d_, t}; + } + + int getCount(int destination, int startTime, int endTime) { + auto& ls = d[destination]; + int k = idx[destination]; + auto i = lower_bound(ls.begin() + k, ls.end(), startTime); + auto j = lower_bound(ls.begin() + k, ls.end(), endTime + 1); + return j - i; + } +}; + +/** + * Your Router object will be instantiated and called as such: + * Router* obj = new Router(memoryLimit); + * bool param_1 = obj->addPacket(source,destination,timestamp); + * vector param_2 = obj->forwardPacket(); + * int param_3 = obj->getCount(destination,startTime,endTime); + */ diff --git a/solution/3500-3599/3508.Implement Router/Solution.go b/solution/3500-3599/3508.Implement Router/Solution.go new file mode 100644 index 0000000000000..b3c14dbd53414 --- /dev/null +++ b/solution/3500-3599/3508.Implement Router/Solution.go @@ -0,0 +1,63 @@ +type Router struct { + lim int + vis map[int64]struct{} + q [][3]int + idx map[int]int + d map[int][]int +} + +func Constructor(memoryLimit int) Router { + return Router{ + lim: memoryLimit, + vis: make(map[int64]struct{}), + q: make([][3]int, 0), + idx: make(map[int]int), + d: make(map[int][]int), + } +} + +func (this *Router) f(a, b, c int) int64 { + return int64(a)<<46 | int64(b)<<29 | int64(c) +} + +func (this *Router) AddPacket(source int, destination int, timestamp int) bool { + x := this.f(source, destination, timestamp) + if _, ok := this.vis[x]; ok { + return false + } + this.vis[x] = struct{}{} + if len(this.q) >= this.lim { + this.ForwardPacket() + } + this.q = append(this.q, [3]int{source, destination, timestamp}) + this.d[destination] = append(this.d[destination], timestamp) + return true +} + +func (this *Router) ForwardPacket() []int { + if len(this.q) == 0 { + return []int{} + } + packet := this.q[0] + this.q = this.q[1:] + s, d, t := packet[0], packet[1], packet[2] + delete(this.vis, this.f(s, d, t)) + this.idx[d]++ + return []int{s, d, t} +} + +func (this *Router) GetCount(destination int, startTime int, endTime int) int { + ls := this.d[destination] + k := this.idx[destination] + i := sort.Search(len(ls)-k, func(i int) bool { return ls[i+k] >= startTime }) + k + j := sort.Search(len(ls)-k, func(i int) bool { return ls[i+k] >= endTime+1 }) + k + return j - i +} + +/** + * Your Router object will be instantiated and called as such: + * obj := Constructor(memoryLimit) + * param_1 := obj.AddPacket(source,destination,timestamp) + * param_2 := obj.ForwardPacket() + * param_3 := obj.GetCount(destination,startTime,endTime) + */ diff --git a/solution/3500-3599/3508.Implement Router/Solution.java b/solution/3500-3599/3508.Implement Router/Solution.java new file mode 100644 index 0000000000000..41006c45a53f8 --- /dev/null +++ b/solution/3500-3599/3508.Implement Router/Solution.java @@ -0,0 +1,69 @@ +class Router { + private int lim; + private Set vis = new HashSet<>(); + private Deque q = new ArrayDeque<>(); + private Map idx = new HashMap<>(); + private Map> d = new HashMap<>(); + + public Router(int memoryLimit) { + this.lim = memoryLimit; + } + + public boolean addPacket(int source, int destination, int timestamp) { + long x = f(source, destination, timestamp); + if (vis.contains(x)) { + return false; + } + vis.add(x); + if (q.size() >= lim) { + forwardPacket(); + } + q.offer(new int[] {source, destination, timestamp}); + d.computeIfAbsent(destination, k -> new ArrayList<>()).add(timestamp); + return true; + } + + public int[] forwardPacket() { + if (q.isEmpty()) { + return new int[] {}; + } + int[] packet = q.poll(); + int s = packet[0], d_ = packet[1], t = packet[2]; + vis.remove(f(s, d_, t)); + idx.merge(d_, 1, Integer::sum); + return new int[] {s, d_, t}; + } + + private long f(int a, int b, int c) { + return ((long) a << 46) | ((long) b << 29) | (long) c; + } + + public int getCount(int destination, int startTime, int endTime) { + List ls = d.getOrDefault(destination, List.of()); + int k = idx.getOrDefault(destination, 0); + int i = lowerBound(ls, startTime, k); + int j = lowerBound(ls, endTime + 1, k); + return j - i; + } + + private int lowerBound(List list, int target, int fromIndex) { + int l = fromIndex, r = list.size(); + while (l < r) { + int m = (l + r) >>> 1; + if (list.get(m) < target) { + l = m + 1; + } else { + r = m; + } + } + return l; + } +} + +/** + * 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); + */ diff --git a/solution/3500-3599/3508.Implement Router/Solution.py b/solution/3500-3599/3508.Implement Router/Solution.py new file mode 100644 index 0000000000000..13f39b51ae395 --- /dev/null +++ b/solution/3500-3599/3508.Implement Router/Solution.py @@ -0,0 +1,44 @@ +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) diff --git a/solution/3500-3599/3508.Implement Router/Solution.rs b/solution/3500-3599/3508.Implement Router/Solution.rs new file mode 100644 index 0000000000000..ffe981915293f --- /dev/null +++ b/solution/3500-3599/3508.Implement Router/Solution.rs @@ -0,0 +1,61 @@ +use std::collections::{HashSet, HashMap, VecDeque}; + +struct Router { + lim: usize, + vis: HashSet, + q: VecDeque<(i32, i32, i32)>, + idx: HashMap, + d: HashMap>, +} + +impl Router { + fn new(memory_limit: i32) -> Self { + Router { + lim: memory_limit as usize, + vis: HashSet::new(), + q: VecDeque::new(), + idx: HashMap::new(), + d: HashMap::new(), + } + } + + fn f(a: i32, b: i32, c: i32) -> i64 { + ((a as i64) << 46) | ((b as i64) << 29) | (c as i64) + } + + fn add_packet(&mut self, source: i32, destination: i32, timestamp: i32) -> bool { + let x = Self::f(source, destination, timestamp); + if self.vis.contains(&x) { + return false; + } + self.vis.insert(x); + if self.q.len() >= self.lim { + self.forward_packet(); + } + self.q.push_back((source, destination, timestamp)); + self.d.entry(destination).or_default().push(timestamp); + true + } + + fn forward_packet(&mut self) -> Vec { + if let Some((s, d, t)) = self.q.pop_front() { + self.vis.remove(&Self::f(s, d, t)); + *self.idx.entry(d).or_insert(0) += 1; + vec![s, d, t] + } else { + vec![] + } + } + + fn get_count(&self, destination: i32, start_time: i32, end_time: i32) -> i32 { + let ls = self.d.get(&destination); + if ls.is_none() { + return 0; + } + let ls = ls.unwrap(); + let k = *self.idx.get(&destination).unwrap_or(&0); + let i = k + ls[k..].partition_point(|&x| x < start_time); + let j = k + ls[k..].partition_point(|&x| x < end_time + 1); + (j - i) as i32 + } +} diff --git a/solution/3500-3599/3508.Implement Router/Solution.ts b/solution/3500-3599/3508.Implement Router/Solution.ts new file mode 100644 index 0000000000000..a9f0bd60bb4a7 --- /dev/null +++ b/solution/3500-3599/3508.Implement Router/Solution.ts @@ -0,0 +1,76 @@ +class Router { + private lim: number; + private vis: Set; + private q: [number, number, number][]; + private idx: Map; + private d: Map; + + constructor(memoryLimit: number) { + this.lim = memoryLimit; + this.vis = new Set(); + this.q = []; + this.idx = new Map(); + this.d = new Map(); + } + + private f(a: number, b: number, c: number): number { + return ((BigInt(a) << 46n) | (BigInt(b) << 29n) | BigInt(c)) as unknown as number; + } + + addPacket(source: number, destination: number, timestamp: number): boolean { + const x = this.f(source, destination, timestamp); + if (this.vis.has(x)) { + return false; + } + this.vis.add(x); + if (this.q.length >= this.lim) { + this.forwardPacket(); + } + this.q.push([source, destination, timestamp]); + if (!this.d.has(destination)) { + this.d.set(destination, []); + } + this.d.get(destination)!.push(timestamp); + return true; + } + + forwardPacket(): number[] { + if (this.q.length === 0) { + return []; + } + const [s, d, t] = this.q.shift()!; + this.vis.delete(this.f(s, d, t)); + this.idx.set(d, (this.idx.get(d) ?? 0) + 1); + return [s, d, t]; + } + + getCount(destination: number, startTime: number, endTime: number): number { + const ls = this.d.get(destination) ?? []; + const k = this.idx.get(destination) ?? 0; + const i = this.lowerBound(ls, startTime, k); + const j = this.lowerBound(ls, endTime + 1, k); + return j - i; + } + + private lowerBound(arr: number[], target: number, from: number): number { + let l = from, + r = arr.length; + while (l < r) { + const m = Math.floor((l + r) / 2); + if (arr[m] < target) { + l = m + 1; + } else { + r = m; + } + } + return l; + } +} + +/** + * Your Router object will be instantiated and called as such: + * var obj = new Router(memoryLimit) + * var param_1 = obj.addPacket(source,destination,timestamp) + * var param_2 = obj.forwardPacket() + * var param_3 = obj.getCount(destination,startTime,endTime) + */