代码随想录day11|239滑动窗口最大值347前k个高频元素|01笔记

111 阅读1分钟
  • 239滑动窗口最大值

  • 代码随想录 (programmercarl.com)
  • 第一印象

  • 可以利用有序的栈,栈顶就是滑动窗口范围内的最大值,窗口本次变动滑过的值用-k来求,如果等于最大值,则pop。每次移动时比较栈顶并压入即可。
  • 遇到错误

  •     func maxSlidingWindow(nums []int, k int) []int {
            st := []int{}
            win := make([]int,k)
            win = nums[0:k]
            for _, i:=range win {
                if len(st)==0 {
                    st = append(st, i)   
                    continue
                } else if i >= st[len(st)-1] {
                    st=append(st, i)
                } 
            }
            ans := make([]int,0)
            ans = append(ans, st[len(st)-1])
            for j:=k;j<len(nums);j++ {
                if nums[j-k] == st[len(st)-1] {
                    if len(st)-1==0 {
                        st = make([]int,0)
                    } else {
                        st = st[:len(st)-1]
                    }
                }
                if len(st)==0 || nums[j]>=st[len(st)-1] {
                    st = append(st, nums[j])
                }
                ans = append(ans, st[len(st)-1])
            }
            return ans
        }
    
  • image.png
  • 错误原因:只维护了第一个值与最大值,窗口元素不完整。
  • 解决办法:维护整个窗口的单调队列
  • 解题代码

  •     // 封装单调队列的方式解题
        type MyQueue struct {
            queue []int
        }
        
    
        func NewMyQueue() *MyQueue {
            return &MyQueue{
                queue: make([]int, 0),
            }
        }
        
        func (m *MyQueue) Front() int {
            return m.queue[0]
        }
        
        func (m *MyQueue) Back() int {
            return m.queue[len(m.queue)-1]
        }
        
        func (m *MyQueue) Empty() bool {
            return len(m.queue) == 0
        }
        
        func (m *MyQueue) Push(val int) {
            for !m.Empty() && val > m.Back() {
                m.queue = m.queue[:len(m.queue)-1]
            }
            m.queue = append(m.queue, val)
        }
        
        func (m *MyQueue) Pop(val int) {
            if !m.Empty() && val == m.Front() {
                m.queue = m.queue[1:]
            }
        }
        
        func maxSlidingWindow(nums []int, k int) []int {
            queue := NewMyQueue()
            length := len(nums)
            res := make([]int, 0)
            // 先将前k个元素放入队列
            for i := 0; i < k; i++ {
                queue.Push(nums[i])
            }
            // 记录前k个元素的最大值
            res = append(res, queue.Front())
        
            for i := k; i < length; i++ {
                // 滑动窗口移除最前面的元素
                queue.Pop(nums[i-k])
                // 滑动窗口添加最后面的元素
                queue.Push(nums[i])
                // 记录最大值
                res = append(res, queue.Front())
            }
            return res
        }
    
  • 347前k个高频元素

  • 代码随想录 (programmercarl.com)
  • 第一印象

  • 可以利用kv形式的容器存储元素及其频率,然后还需要排序。
  • 解题代码

Go基础:heap的介绍与使用 - 知乎 (zhihu.com)

    //方法一:小顶堆
    func topKFrequent(nums []int, k int) []int {
        map_num:=map[int]int{}
        //记录每个元素出现的次数
        for _,item:=range nums{
            map_num[item]++
        }
        h:=&IHeap{}
        heap.Init(h)
        //所有元素入堆,堆的长度为k
        for key,value:=range map_num{
            heap.Push(h,[2]int{key,value})
            if h.Len()>k{
                heap.Pop(h)
            }
        }
        res:=make([]int,k)
        //按顺序返回堆中的元素
        for i:=0;i<k;i++{
            res[k-i-1]=heap.Pop(h).([2]int)[0]
        }
        return res
    }
    
    //构建小顶堆
    type IHeap [][2]int
    
    func (h IHeap) Len()int {
        return len(h)
    }
    
    func (h IHeap) Less (i,j int) bool {
        return h[i][1]<h[j][1]
    }
    
    func (h IHeap) Swap(i,j int) {
        h[i],h[j]=h[j],h[i]
    }
    
    func (h *IHeap) Push(x interface{}){
        *h=append(*h,x.([2]int))
    }
    func (h *IHeap) Pop() interface{}{
        old:=*h
        n:=len(old)
        x:=old[n-1]
        *h=old[0:n-1]
        return x
    }
    
    
    //方法二:利用O(nlogn)排序
    func topKFrequent(nums []int, k int) []int {
        ans:=[]int{}
        map_num:=map[int]int{}
        for _,item:=range nums {
            map_num[item]++
        }
        for key,_:=range map_num{
            ans=append(ans,key)
        }
        //核心思想:排序
        //可以不用包函数,自己实现快排
        sort.Slice(ans,func (a,b int)bool{
            return map_num[ans[a]]>map_num[ans[b]]
        })
        return ans[:k]
    }