春招打卡|数据流中的第k大元素|go实现

77 阅读2分钟

Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情

一、题目描述

设计一个找到数据流中第 k 大元素的类(class)。注意是排序后的第 k 大元素,不是第 k 个不同的元素。

KthLargest(int k, int[] nums) 使用整数 k 和整数流 nums 初始化对象。 int add(int val) 将 val 插入数据流 nums 后,返回当前数据流中第 k 大的元素。

二、思路分析

  1. 第K个最大元素,可以基于快速选择第k大元素|快速选择算法,也可以基于大根堆实现基于堆排序的选择算法,删除前k-1个元素,堆顶为第k个最大元素。
  2. 设计KthLargst类,使得每次add操作能够返回第k大元素。
  3. 这是一道简单题,最简单的方式是使用内置的小顶堆数据结构,堆中维持k个元素,堆顶为最小元素也就是第k大个元素。
  4. 每次add操作时如果堆的大小超过了K,则推出堆顶元素,维持堆内有k个元素。
  5. 初始化的时间复杂度为O(nlogk),单次插入的时间复杂度为O(logk)

三、AC 代码

type KthLargest struct {
   sort.IntSlice
   k int
}

func Constructor(k int, nums []int) KthLargest {
   kt := KthLargest {
       k :k,
   }
   for _,v := range nums {
       kt.Add(v)
   }
   return kt
}

func (kt *KthLargest) Add(val int) int {
    heap.Push(kt,val)
    if kt.Len() > kt.k {
        heap.Pop(kt)
    }
    return kt.IntSlice[0]
}
//实现go中的堆接口
func (kt *KthLargest) Push(v interface{}) {
    kt.IntSlice = append(kt.IntSlice,v.(int))
}

func(kt *KthLargest) Pop() interface{} {
    a := kt.IntSlice
    v := kt.IntSlice[len(a) - 1]
    kt.IntSlice = a[:len(a)-1]
    return v
}

四、总结

数据流中的第K个最大元素,意味着数据长度不是固定的,无法使用快速选择算法,最好使用堆结构,动态接受数据。go中内置的heap不是非常好用,使用java或者c++的优先队列会更加方便做题。