From 2a0998864c6a4ca81cb7e48f3b320af8b76057fd Mon Sep 17 00:00:00 2001 From: 0xff-dev Date: Sat, 20 Sep 2025 09:36:32 +0800 Subject: [PATCH] Add solution and test-cases for problem 3508 --- .../3501-3600/3508.Implement-Router/README.md | 74 ++++++++++++--- .../3508.Implement-Router/Solution.go | 95 ++++++++++++++++++- .../3508.Implement-Router/Solution_test.go | 32 +++++-- 3 files changed, 176 insertions(+), 25 deletions(-) diff --git a/leetcode/3501-3600/3508.Implement-Router/README.md b/leetcode/3501-3600/3508.Implement-Router/README.md index 313346934..ab2dbad05 100755 --- a/leetcode/3501-3600/3508.Implement-Router/README.md +++ b/leetcode/3501-3600/3508.Implement-Router/README.md @@ -1,28 +1,76 @@ # [3508.Implement Router][title] -> [!WARNING|style:flat] -> This question is temporarily unanswered if you have good ideas. Welcome to [Create Pull Request PR](https://github.com/kylesliu/awesome-golang-algorithm) - ## Description +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`, and `timestamp` already exists in the router. +- Return `true` if the packet is successfully added (i.e., it is not a duplicate); otherwise return `false`. + +` 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: a = "11", b = "1" -Output: "100" -``` +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 -### 思路1 -> ... -Implement Router -```go +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); // Initialize Router 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 []. +``` ## 结语 diff --git a/leetcode/3501-3600/3508.Implement-Router/Solution.go b/leetcode/3501-3600/3508.Implement-Router/Solution.go index d115ccf5e..53511e15a 100644 --- a/leetcode/3501-3600/3508.Implement-Router/Solution.go +++ b/leetcode/3501-3600/3508.Implement-Router/Solution.go @@ -1,5 +1,96 @@ package Solution -func Solution(x bool) bool { - return x +import "sort" + +type Router struct { + memoryLimit int + queue [][3]int + // source, dest, timestamp + in map[[3]int]struct{} + + // dest: [source, timestamp] + dest map[int][]int +} + +func Constructor(memoryLimit int) Router { + return Router{ + memoryLimit: memoryLimit, + queue: make([][3]int, 0), + in: map[[3]int]struct{}{}, + dest: make(map[int][]int), + } +} + +func (this *Router) AddPacket(source int, destination int, timestamp int) bool { + key := [3]int{source, destination, timestamp} + if _, ok := this.in[key]; ok { + return false + } + this.in[key] = struct{}{} + cur := len(this.queue) + if cur == this.memoryLimit { + _ = this.ForwardPacket() + } + this.queue = append(this.queue, key) + + this.dest[destination] = append(this.dest[destination], timestamp) + return true +} + +func (this *Router) ForwardPacket() []int { + if len(this.queue) == 0 { + return []int{} + } + + first := this.queue[0] + this.queue = this.queue[1:] + delete(this.in, first) + // 同时移除队列的数据 + sources := this.dest[first[1]] + index := sort.Search(len(sources), func(i int) bool { + return sources[i] >= first[2] + }) + sources = append(sources[:index], sources[index+1:]...) + this.dest[first[1]] = sources + return first[:] +} + +func (this *Router) GetCount(destination int, startTime int, endTime int) int { + sources, ok := this.dest[destination] + if !ok { + return 0 + } + start := sort.Search(len(sources), func(i int) bool { + return sources[i] >= startTime + }) + end := sort.Search(len(sources), func(i int) bool { + return sources[i] > endTime + }) + return end - start +} + +type op struct { + name string + source, destination, timestamp int +} + +func Solution(memoryLimit int, ops []op) []any { + ret := make([]any, 0) + c := Constructor(memoryLimit) + for _, o := range ops { + if o.name == "add" { + ret = append(ret, c.AddPacket(o.source, o.destination, o.timestamp)) + continue + } + + if o.name == "for" { + ret = append(ret, c.ForwardPacket()) + continue + } + + if o.name == "get" { + ret = append(ret, c.GetCount(o.source, o.destination, o.timestamp)) + } + } + return ret } diff --git a/leetcode/3501-3600/3508.Implement-Router/Solution_test.go b/leetcode/3501-3600/3508.Implement-Router/Solution_test.go index 14ff50eb4..dcedcbfce 100644 --- a/leetcode/3501-3600/3508.Implement-Router/Solution_test.go +++ b/leetcode/3501-3600/3508.Implement-Router/Solution_test.go @@ -10,30 +10,42 @@ func TestSolution(t *testing.T) { // 测试用例 cases := []struct { name string - inputs bool - expect bool + inputs int + ops []op + expect []any }{ - {"TestCase", true, true}, - {"TestCase", true, true}, - {"TestCase", false, false}, + {"TestCase1", 3, []op{ + {"add", 1, 4, 90}, + {"add", 2, 5, 90}, + {"add", 1, 4, 90}, + {"add", 3, 5, 95}, + {"add", 4, 5, 105}, + {"for", 0, 0, 0}, + {"add", 5, 2, 110}, + {"get", 5, 100, 110}, + }, []any{true, true, false, true, true, []int{2, 5, 90}, true, 1}}, + + {"TestCase12", 2, []op{ + {"add", 7, 4, 90}, {"for", 0, 0, 0}, {"for", 0, 0, 0}, + }, []any{true, []int{7, 4, 90}, []int{}}}, } // 开始测试 for i, c := range cases { t.Run(c.name+" "+strconv.Itoa(i), func(t *testing.T) { - got := Solution(c.inputs) + got := Solution(c.inputs, c.ops) if !reflect.DeepEqual(got, c.expect) { - t.Fatalf("expected: %v, but got: %v, with inputs: %v", - c.expect, got, c.inputs) + t.Fatalf("expected: %v, but got: %v, with inputs: %v %v", + c.expect, got, c.inputs, c.ops) } }) } } -// 压力测试 +// 压力测试 func BenchmarkSolution(b *testing.B) { } -// 使用案列 +// 使用案列 func ExampleSolution() { }