Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 61 additions & 13 deletions leetcode/3501-3600/3508.Implement-Router/README.md
Original file line number Diff line number Diff line change
@@ -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 [].
```

## 结语

Expand Down
95 changes: 93 additions & 2 deletions leetcode/3501-3600/3508.Implement-Router/Solution.go
Original file line number Diff line number Diff line change
@@ -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
}
32 changes: 22 additions & 10 deletions leetcode/3501-3600/3508.Implement-Router/Solution_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
}
Loading