Week 15 @ 2025 算法周记【随机 + 队列】

随机

LC 382. Linked List Random Node 链表随机节点

https://leetcode.com/problems/linked-list-random-node/

/** * Definition for singly-linked list. * type ListNode struct { * Val int * Next *ListNode * } */ type Solution struct { head *ListNode } func Constructor(head *ListNode) Solution { return Solution { head: head, } } func (this *Solution) GetRandom() int { v := -1 i := 0 for h := this.head; h != nil; h = h.Next { i++ if rand.Intn(i) == 0 { v = h.Val } } return v } /** * Your Solution object will be instantiated and called as such: * obj := Constructor(head); * param_1 := obj.GetRandom(); */

LC 398. Random Pick Index

https://leetcode.com/problems/random-pick-index/

预处理

type Solution struct { numsMap map[int][]int } func Constructor(nums []int) Solution { numsMap := make(map[int][]int, len(nums)) for i, v := range nums { numsMap[v] = append(numsMap[v], i) } return Solution { numsMap: numsMap, } } func (this *Solution) Pick(target int) (result int) { indexes := this.numsMap[target] return indexes[rand.Intn(len(indexes))] } /** * Your Solution object will be instantiated and called as such: * obj := Constructor(nums); * param_1 := obj.Pick(target); */

水塘抽样(TLE)

type Solution struct { nums []int } func Constructor(nums []int) Solution { return Solution { nums: nums, } } func (this *Solution) Pick(target int) (result int) { k := 0 for i, v := range this.nums { if v != target { continue } k++ if rand.Intn(k) == 0 { result = i } } return } /** * Your Solution object will be instantiated and called as such: * obj := Constructor(nums); * param_1 := obj.Pick(target); */

队列

LC 933. Number of Recent Calls

https://leetcode.com/problems/number-of-recent-calls/description/

type RecentCounter struct { requests []int } func Constructor() RecentCounter { return RecentCounter { requests: []int{}, } } func (this *RecentCounter) Ping(t int) int { this.requests = append(this.requests, t) start := 0 for i := 0; i < len(this.requests); i++ { if this.requests[i] < t - 3000 { start = i+1 } } this.requests = this.requests[start:] return len(this.requests) } /** * Your RecentCounter object will be instantiated and called as such: * obj := Constructor(); * param_1 := obj.Ping(t); */

进一步强化「队列」属性

type RecentCounter struct { requests []int } func Constructor() RecentCounter { return RecentCounter { requests: []int{}, } } func (this *RecentCounter) Ping(t int) int { this.requests = append(this.requests, t) for this.requests[0] < t - 3000 { this.requests = this.requests[1:] } return len(this.requests) } /** * Your RecentCounter object will be instantiated and called as such: * obj := Constructor(); * param_1 := obj.Ping(t); */

LC 622. Design Circular Queue 设计循环队列

https://leetcode.com/problems/design-circular-queue/description/

type MyCircularQueue struct { els []int head int n int maxN int } func Constructor(k int) MyCircularQueue { return MyCircularQueue { els: make([]int, k), head: -1, n: 0, maxN: k, } } func (this *MyCircularQueue) EnQueue(value int) bool { if this.n == this.maxN { return false } if this.n == 0 { this.head = 0 this.els[0] = value this.n = 1 return true } nextIndex := (this.head + this.n) % this.maxN this.els[nextIndex] = value this.n++ return true } func (this *MyCircularQueue) DeQueue() bool { if this.n == 0 { return false } this.n-- this.head = (this.head + 1) % this.maxN return true } func (this *MyCircularQueue) Front() int { if this.n == 0 { return -1 } return this.els[this.head] } func (this *MyCircularQueue) Rear() int { if this.n == 0 { return -1 } i := (this.head + this.n - 1) % this.maxN return this.els[i] } func (this *MyCircularQueue) IsEmpty() bool { return this.n == 0 } func (this *MyCircularQueue) IsFull() bool { return this.n == this.maxN } /** * Your MyCircularQueue object will be instantiated and called as such: * obj := Constructor(k); * param_1 := obj.EnQueue(value); * param_2 := obj.DeQueue(); * param_3 := obj.Front(); * param_4 := obj.Rear(); * param_5 := obj.IsEmpty(); * param_6 := obj.IsFull(); */

同时记录 first & last

import "errors" // 底层用数组实现队列 type ArrayQueue[E any] struct { size int data []E first int last int } const INIT_CAP = 2 func NewArrayQueue[E any](initCap int) *ArrayQueue[E] { return &ArrayQueue[E]{ size: 0, data: make([]E, initCap), first: 0, last: 0, } } func NewArrayQueueDefault[E any]() *ArrayQueue[E] { // 不传参数,默认大小为 INIT_CAP return NewArrayQueue[E](INIT_CAP) } // 增 func (q *ArrayQueue[E]) Enqueue(e E) { if q.size == len(q.data) { q.resize(q.size * 2) } q.data[q.last] = e q.last++ if q.last == len(q.data) { q.last = 0 } q.size++ } // 删 func (q *ArrayQueue[E]) Dequeue() (E, error) { if q.isEmpty() { var zero E return zero, errors.New("no such element") } if q.size == len(q.data)/4 { q.resize(len(q.data) / 2) } oldVal := q.data[q.first] var zero E q.data[q.first] = zero q.first++ if q.first == len(q.data) { q.first = 0 } q.size-- return oldVal, nil } func (q *ArrayQueue[E]) resize(newCap int) { temp := make([]E, newCap) // first ----- last // --- last first --- for i := 0; i < q.size; i++ { temp[i] = q.data[(q.first+i)%len(q.data)] } q.first = 0 q.last = q.size q.data = temp } // 查 func (q *ArrayQueue[E]) PeekFirst() (E, error) { if q.isEmpty() { var zero E return zero, errors.New("no such element") } return q.data[q.first], nil } func (q *ArrayQueue[E]) PeekLast() (E, error) { if q.isEmpty() { var zero E return zero, errors.New("no such element") } if q.last == 0 { return q.data[len(q.data)-1], nil } return q.data[q.last-1], nil } func (q *ArrayQueue[E]) Size() int { return q.size } func (q *ArrayQueue[E]) isEmpty() bool { return q.size == 0 } type MyCircularQueue struct { q *ArrayQueue[int] maxCap int } func Constructor(k int) MyCircularQueue { return MyCircularQueue{ q: NewArrayQueue[int](k), maxCap: k, } } func (cq *MyCircularQueue) EnQueue(value int) bool { if cq.q.Size() == cq.maxCap { return false } cq.q.Enqueue(value) return true } func (cq *MyCircularQueue) DeQueue() bool { if cq.q.isEmpty() { return false } _, _ = cq.q.Dequeue() return true } func (cq *MyCircularQueue) Front() int { if cq.q.isEmpty() { return -1 } val, _ := cq.q.PeekFirst() return val } func (cq *MyCircularQueue) Rear() int { if cq.q.isEmpty() { return -1 } val, _ := cq.q.PeekLast() return val } func (cq *MyCircularQueue) IsEmpty() bool { return cq.q.isEmpty() } func (cq *MyCircularQueue) IsFull() bool { return cq.q.Size() == cq.maxCap }