Skip to content

Commit 8c54b23

Browse files
authored
Merge pull request #1319 from 0xff-dev/3508
Add solution and test-cases for problem 3508
2 parents 8f4f80c + 2a09988 commit 8c54b23

File tree

3 files changed

+176
-25
lines changed

3 files changed

+176
-25
lines changed

leetcode/3501-3600/3508.Implement-Router/README.md

Lines changed: 61 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,76 @@
11
# [3508.Implement Router][title]
22

3-
> [!WARNING|style:flat]
4-
> This question is temporarily unanswered if you have good ideas. Welcome to [Create Pull Request PR](https://github.com/kylesliu/awesome-golang-algorithm)
5-
63
## Description
4+
Design a data structure that can efficiently manage data packets in a network router. Each data packet consists of the following attributes:
5+
6+
- `source`: A unique identifier for the machine that generated the packet.
7+
- `destination`: A unique identifier for the target machine.
8+
- `timestamp`: The time at which the packet arrived at the router.
9+
10+
Implement the `Router` class:
11+
12+
`Router(int memoryLimit)`: Initializes the Router object with a fixed memory limit.
13+
14+
- `memoryLimit` is the **maximum** number of packets the router can store at any given time.
15+
- If adding a new packet would exceed this limit, the **oldest** packet must be removed to free up space.
16+
17+
` bool addPacket(int source, int destination, int timestamp)`: Adds a packet with the given attributes to the router.
18+
19+
- A packet is considered a duplicate if another packet with the same `source`, `destination`, and `timestamp` already exists in the router.
20+
- Return `true` if the packet is successfully added (i.e., it is not a duplicate); otherwise return `false`.
21+
22+
` int[] forwardPacket()`: Forwards the next packet in FIFO (First In First Out) order.
23+
24+
- Remove the packet from storage.
25+
- Return the packet as an array `[source, destination, timestamp]`.
26+
- If there are no packets to forward, return an empty array.
27+
28+
`int getCount(int destination, int startTime, int endTime)`:
29+
30+
- 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]`.
31+
32+
**Note** that queries for `addPacket` will be made in increasing order of `timestamp`.
733

834
**Example 1:**
935

1036
```
11-
Input: a = "11", b = "1"
12-
Output: "100"
13-
```
37+
Input:
38+
["Router", "addPacket", "addPacket", "addPacket", "addPacket", "addPacket", "forwardPacket", "addPacket", "getCount"]
39+
[[3], [1, 4, 90], [2, 5, 90], [1, 4, 90], [3, 5, 95], [4, 5, 105], [], [5, 2, 110], [5, 100, 110]]
1440
15-
## 题意
16-
> ...
41+
Output:
42+
[null, true, true, false, true, true, [2, 5, 90], true, 1]
1743
18-
## 题解
44+
Explanation
1945
20-
### 思路1
21-
> ...
22-
Implement Router
23-
```go
46+
Router router = new Router(3); // Initialize Router with memoryLimit of 3.
47+
router.addPacket(1, 4, 90); // Packet is added. Return True.
48+
router.addPacket(2, 5, 90); // Packet is added. Return True.
49+
router.addPacket(1, 4, 90); // This is a duplicate packet. Return False.
50+
router.addPacket(3, 5, 95); // Packet is added. Return True
51+
router.addPacket(4, 5, 105); // Packet is added, [1, 4, 90] is removed as number of packets exceeds memoryLimit. Return True.
52+
router.forwardPacket(); // Return [2, 5, 90] and remove it from router.
53+
router.addPacket(5, 2, 110); // Packet is added. Return True.
54+
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.
2455
```
2556

57+
**Example 2:**
58+
59+
```
60+
Input:
61+
["Router", "addPacket", "forwardPacket", "forwardPacket"]
62+
[[2], [7, 4, 90], [], []]
63+
64+
Output:
65+
[null, true, [7, 4, 90], []]
66+
67+
Explanation
68+
69+
Router router = new Router(2); // Initialize Router with memoryLimit of 2.
70+
router.addPacket(7, 4, 90); // Return True.
71+
router.forwardPacket(); // Return [7, 4, 90].
72+
router.forwardPacket(); // There are no packets left, return [].
73+
```
2674

2775
## 结语
2876

Lines changed: 93 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,96 @@
11
package Solution
22

3-
func Solution(x bool) bool {
4-
return x
3+
import "sort"
4+
5+
type Router struct {
6+
memoryLimit int
7+
queue [][3]int
8+
// source, dest, timestamp
9+
in map[[3]int]struct{}
10+
11+
// dest: [source, timestamp]
12+
dest map[int][]int
13+
}
14+
15+
func Constructor(memoryLimit int) Router {
16+
return Router{
17+
memoryLimit: memoryLimit,
18+
queue: make([][3]int, 0),
19+
in: map[[3]int]struct{}{},
20+
dest: make(map[int][]int),
21+
}
22+
}
23+
24+
func (this *Router) AddPacket(source int, destination int, timestamp int) bool {
25+
key := [3]int{source, destination, timestamp}
26+
if _, ok := this.in[key]; ok {
27+
return false
28+
}
29+
this.in[key] = struct{}{}
30+
cur := len(this.queue)
31+
if cur == this.memoryLimit {
32+
_ = this.ForwardPacket()
33+
}
34+
this.queue = append(this.queue, key)
35+
36+
this.dest[destination] = append(this.dest[destination], timestamp)
37+
return true
38+
}
39+
40+
func (this *Router) ForwardPacket() []int {
41+
if len(this.queue) == 0 {
42+
return []int{}
43+
}
44+
45+
first := this.queue[0]
46+
this.queue = this.queue[1:]
47+
delete(this.in, first)
48+
// 同时移除队列的数据
49+
sources := this.dest[first[1]]
50+
index := sort.Search(len(sources), func(i int) bool {
51+
return sources[i] >= first[2]
52+
})
53+
sources = append(sources[:index], sources[index+1:]...)
54+
this.dest[first[1]] = sources
55+
return first[:]
56+
}
57+
58+
func (this *Router) GetCount(destination int, startTime int, endTime int) int {
59+
sources, ok := this.dest[destination]
60+
if !ok {
61+
return 0
62+
}
63+
start := sort.Search(len(sources), func(i int) bool {
64+
return sources[i] >= startTime
65+
})
66+
end := sort.Search(len(sources), func(i int) bool {
67+
return sources[i] > endTime
68+
})
69+
return end - start
70+
}
71+
72+
type op struct {
73+
name string
74+
source, destination, timestamp int
75+
}
76+
77+
func Solution(memoryLimit int, ops []op) []any {
78+
ret := make([]any, 0)
79+
c := Constructor(memoryLimit)
80+
for _, o := range ops {
81+
if o.name == "add" {
82+
ret = append(ret, c.AddPacket(o.source, o.destination, o.timestamp))
83+
continue
84+
}
85+
86+
if o.name == "for" {
87+
ret = append(ret, c.ForwardPacket())
88+
continue
89+
}
90+
91+
if o.name == "get" {
92+
ret = append(ret, c.GetCount(o.source, o.destination, o.timestamp))
93+
}
94+
}
95+
return ret
596
}

leetcode/3501-3600/3508.Implement-Router/Solution_test.go

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,30 +10,42 @@ func TestSolution(t *testing.T) {
1010
// 测试用例
1111
cases := []struct {
1212
name string
13-
inputs bool
14-
expect bool
13+
inputs int
14+
ops []op
15+
expect []any
1516
}{
16-
{"TestCase", true, true},
17-
{"TestCase", true, true},
18-
{"TestCase", false, false},
17+
{"TestCase1", 3, []op{
18+
{"add", 1, 4, 90},
19+
{"add", 2, 5, 90},
20+
{"add", 1, 4, 90},
21+
{"add", 3, 5, 95},
22+
{"add", 4, 5, 105},
23+
{"for", 0, 0, 0},
24+
{"add", 5, 2, 110},
25+
{"get", 5, 100, 110},
26+
}, []any{true, true, false, true, true, []int{2, 5, 90}, true, 1}},
27+
28+
{"TestCase12", 2, []op{
29+
{"add", 7, 4, 90}, {"for", 0, 0, 0}, {"for", 0, 0, 0},
30+
}, []any{true, []int{7, 4, 90}, []int{}}},
1931
}
2032

2133
// 开始测试
2234
for i, c := range cases {
2335
t.Run(c.name+" "+strconv.Itoa(i), func(t *testing.T) {
24-
got := Solution(c.inputs)
36+
got := Solution(c.inputs, c.ops)
2537
if !reflect.DeepEqual(got, c.expect) {
26-
t.Fatalf("expected: %v, but got: %v, with inputs: %v",
27-
c.expect, got, c.inputs)
38+
t.Fatalf("expected: %v, but got: %v, with inputs: %v %v",
39+
c.expect, got, c.inputs, c.ops)
2840
}
2941
})
3042
}
3143
}
3244

33-
//压力测试
45+
// 压力测试
3446
func BenchmarkSolution(b *testing.B) {
3547
}
3648

37-
//使用案列
49+
// 使用案列
3850
func ExampleSolution() {
3951
}

0 commit comments

Comments
 (0)