zoukankan      html  css  js  c++  java
  • 双端队列

    滑动窗口内最大数

    题目来源

    LeetCode 239. Sliding Window Maximum

    精简解题

    方法一

    1. 构建大顶堆,大小为窗口大小k
    2. 窗口内数据入堆,返回最大值
    3. 窗口移动,提测内部移除数据,加入新入窗口数据,返回堆顶最大值
    4. 循环以上步骤,直到结束
    // idx -> 2*idx+1, 2*idx+2
    // (idx-1)/2 -> idx
    func heappush(w []int, val int) []int {
    	var idx, idxN int = len(w), 0
    	w = append(w, val)
    	for idx > 0 {
    		idxN = (idx-1)/2
    		if w[idxN] < w[idx] {
    			w[idx], w[idxN] = w[idxN], w[idx]
    		} else {
    			break
    		}
    		idx = idxN
    	}
    	return w
    }
    
    func heappop(w []int) ([]int, int) {
    	var idx, idxN int = 0, 0
    	val := w[0]
    	w[0] = w[len(w)-1]
    	w = w[:len(w)-1]
    	for idx < len(w) {
    		idxN1, idxN2 := 2*idx+1, 2*idx+2
    		if idxN1>=len(w) || w[idxN1]<w[idx] {
    			idxN1 = 0
    		}
    		if idxN2>=len(w) || w[idxN2]<w[idx] {
    			idxN2 = 0
    		}
    		if idxN1>0 && idxN2>0 {
    			if w[idxN1]>w[idxN2] {
    				idxN = idxN1
    			} else {
    				idxN = idxN2
    			}
    		} else if idxN1>0 {
    			idxN = idxN1
    		} else if idxN2>0 {
    			idxN = idxN2
    		} else {
    			break
    		}
    		w[idx], w[idxN] = w[idxN], w[idx]
    		idx = idxN
    	}
    	return w, val
    }
    
    func maxSlidingWindow(nums []int, k int) []int {
    	if k==0 {
    		return []int{}
    	}
    	var window []int = make([]int, 0, k)
    	var dels []int = make([]int, 0)
    	var ans []int = make([]int, 0, len(nums)-k+1)
    	for i:=0; i<k; i++ {
    		window = heappush(window, nums[i])
    	}
    	ans = append(ans, window[0])
    	for i:=k; i<len(nums); i++ {
    		window = heappush(window, nums[i])
    		dels = heappush(dels, nums[i-k])
    		for len(dels)>0 && dels[0]==window[0] {
    			window,_ = heappop(window)
    			dels,_ = heappop(dels)
    		}
    		ans = append(ans, window[0])
    	}
    	return ans
    }
    

    方法二

    1. 构建双端队列
    2. 保持队列大小不超过窗口,以及最大值在出端
    3. 读取新数据,入端操作,和之前的进入的数据比较,之前的数据小则剔除,直到比它大则停止,最大值还在出端
    4. 循环上面步骤,直到结束
    func maxSlidingWindow(nums []int, k int) []int {
      //返回值
      result := make([]int, 0, len(nums)-k)
      //滑动窗口
    	window := make([]int, 0)
    
    	for i := 0; i < len(nums); i++ {
        //双端队列的大小超过窗口大小k,则丢弃最早的值
    		if len(window) > 0 && window[0] <= i-k {
    			window = window[1:]
        }
        //新加入的值和之前加入的值比较,没有新值大的则出去
    		for len(window) > 0 && nums[window[len(window)-1]] < nums[i] {
    			window = window[:len(window)-1]
        }
        //双端队列,入口增加数据
        window = append(window, i)
        //开始存入最大值
    		if i >= k-1 {
    			result = append(result, nums[window[0]])
    		}
    	}
    	return result
    }
    
  • 相关阅读:
    个人编写的一个简单的DB类
    Access绝对地址
    sentry cli 上传source map
    自动旋转的饼图(echarts)
    点会转的折线图还带着柱子
    node 自动化工程部署
    SQL 模糊查询
    编写一个将输入复制到输出的程序,并将其中连续的多个空格用一个空格代替。
    configure、make、make install 解释
    Linux学习笔记(实时更新)
  • 原文地址:https://www.cnblogs.com/weiweng/p/12485900.html
Copyright © 2011-2022 走看看