Golang | Leetcode Golang题解之第480题滑动窗口中位数

题目:

题解:

Go 复制代码
type hp struct {
    sort.IntSlice
    size int
}
func (h *hp) Push(v interface{}) { h.IntSlice = append(h.IntSlice, v.(int)) }
func (h *hp) Pop() interface{}   { a := h.IntSlice; v := a[len(a)-1]; h.IntSlice = a[:len(a)-1]; return v }
func (h *hp) push(v int)         { h.size++; heap.Push(h, v) }
func (h *hp) pop() int           { h.size--; return heap.Pop(h).(int) }
func (h *hp) prune() {
    for h.Len() > 0 {
        num := h.IntSlice[0]
        if h == small {
            num = -num
        }
        if d, has := delayed[num]; has {
            if d > 1 {
                delayed[num]--
            } else {
                delete(delayed, num)
            }
            heap.Pop(h)
        } else {
            break
        }
    }
}

var delayed map[int]int
var small, large *hp

func medianSlidingWindow(nums []int, k int) []float64 {
    delayed = map[int]int{} // 哈希表,记录「延迟删除」的元素,key 为元素,value 为需要删除的次数
    small = &hp{}           // 大根堆,维护较小的一半元素
    large = &hp{}           // 小根堆,维护较大的一半元素
    makeBalance := func() {
        // 调整 small 和 large 中的元素个数,使得二者的元素个数满足要求
        if small.size > large.size+1 { // small 比 large 元素多 2 个
            large.push(-small.pop())
            small.prune() // small 堆顶元素被移除,需要进行 prune
        } else if small.size < large.size { // large 比 small 元素多 1 个
            small.push(-large.pop())
            large.prune() // large 堆顶元素被移除,需要进行 prune
        }
    }
    insert := func(num int) {
        if small.Len() == 0 || num <= -small.IntSlice[0] {
            small.push(-num)
        } else {
            large.push(num)
        }
        makeBalance()
    }
    erase := func(num int) {
        delayed[num]++
        if num <= -small.IntSlice[0] {
            small.size--
            if num == -small.IntSlice[0] {
                small.prune()
            }
        } else {
            large.size--
            if num == large.IntSlice[0] {
                large.prune()
            }
        }
        makeBalance()
    }
    getMedian := func() float64 {
        if k&1 > 0 {
            return float64(-small.IntSlice[0])
        }
        return float64(-small.IntSlice[0]+large.IntSlice[0]) / 2
    }

    for _, num := range nums[:k] {
        insert(num)
    }
    n := len(nums)
    ans := make([]float64, 1, n-k+1)
    ans[0] = getMedian()
    for i := k; i < n; i++ {
        insert(nums[i])
        erase(nums[i-k])
        ans = append(ans, getMedian())
    }
    return ans
}
相关推荐
tachibana231 分钟前
与其他语言相比,使用 Go 有什么好处?
开发语言·后端·golang·go
All for pursuit.12 小时前
【分治-3】347.前K个高频元素
数据结构·c++·算法·leetcode
All for pursuit.13 小时前
【二分查找-2】34.在排序数组中查找元素的第一个和最后一个位置
数据结构·c++·算法·leetcode
hasty13 小时前
限制写了却没生效:OpenTelemetry Go 的 Unicode 截断边界
开发语言·后端·golang
王老师青少年编程16 小时前
2026年9月GESP真题及题解(C++八级):末班车
c++·题解·真题·gesp·八级·2026年9月·末班车
blxr_18 小时前
力扣hot100爬楼梯https://leetcode.cn/problems/climbing-stairs/
算法·leetcode·职场和发展
EatFan19 小时前
Go语言全栈实战:基于 Gin + Vue + JWT + RBAC 从零搭建前后端分离权限管理系统
vue.js·golang·go·vue·gin·jwt·rbac
ZealSinger19 小时前
Go slog生产落地LevelVar与共存
开发语言·后端·golang·go
Navigator_Z19 小时前
LeetCode //C - 1275. Find Winner on a Tic Tac Toe Game
c语言·算法·leetcode
丹宇码农19 小时前
Go 与 Python 协程(Coroutine)对比演示项目
开发语言·python·golang