leetcode239-滑动窗口的最大值

使用双向队列实现

golang版本

话不多说,上代码;有疑问可以交流

// Copyright (c) 仙人抚我顶,邀我共长生 . 2012-2050. All rights reserved.
package _39_滑动窗口最大值

import (
	"fmt"
)

type DoubleSidedList struct {
	begin int // 如果没有值 为-1
	end   int
	data  []int
}

func newDoubleSidedList(l int) *DoubleSidedList {
	list := new(DoubleSidedList)
	list.data = make([]int, l)
	list.begin = -1
	list.end = -1
	return list
}

func (l *DoubleSidedList) pushBack(i int) {
	init := false
	if l.begin == -1 {
		l.begin = 0
		init = true
	}
	l.end = (l.end + 1) % len(l.data)
	l.data[l.end] = i
	if !init && l.end == l.begin {
		fmt.Println("list is full")
	}
}

func (l *DoubleSidedList) pushFront(i int) {
	init := false
	if l.end == -1 {
		l.end = 0
		l.begin = 0
		init = true
	}
	if !init {
		l.begin = (l.begin + len(l.data) - 1) % len(l.data)
	}
	l.data[l.begin] = i
	if !init && l.end == l.begin {
		fmt.Println("list is full")
	}
}

func (l *DoubleSidedList) peekFront() int {
	if l.begin == -1 {
		return -1
	}
	return l.data[l.begin]
}

func (l *DoubleSidedList) peekBack() int {
	if l.end == -1 {
		return -1
	}
	return l.data[l.end]
}

func (l *DoubleSidedList) popFront() int {
	if l.begin == -1 {
		fmt.Println("list is empty")
		return -1
	}

	i := l.data[l.begin]
	if l.begin == l.end {
		l.begin, l.end = -1, -1
	} else {
		l.begin = (l.begin + 1) % len(l.data)
	}
	return i
}

func (l *DoubleSidedList) popBack() int {
	if l.end == -1 {
		fmt.Println("list is empty")
		return -1
	}

	i := l.data[l.end]
	if l.begin == l.end {
		l.begin, l.end = -1, -1
	} else {
		l.end = (l.end + len(l.data) - 1) % len(l.data)
	}
	return i
}

type PriotityList struct {
	indexs    *DoubleSidedList //存储下标
	maxLength int
	data      []int
}

func newPriotityList(list *DoubleSidedList, maxLength int, data []int) *PriotityList {
	return &PriotityList{
		indexs:    list,
		maxLength: maxLength,
		data:      data,
	}
}

func (p *PriotityList) initPush() {
	for i := 0; i < p.maxLength; i++ {
		p.PushIndex(i)
	}
}

func (p *PriotityList) PushIndex(index int) {
	for p.indexs.peekBack() != -1 {
		if p.data[ p.indexs.peekBack()] <= p.data[index] {
			p.indexs.popBack()
		} else {
			break
		}
	}
	p.indexs.pushBack(index)

	p.checkAndClearExpiredIndex()
}

func (p *PriotityList) PeekFrontValue() int {
	return p.data[p.indexs.peekFront()]
}

func (p *PriotityList) checkAndClearExpiredIndex() {
	if p.indexs.peekFront() == -1 {
		return
	}

	begin, end := p.indexs.peekFront(), p.indexs.peekBack()
	if end-begin+1 > p.maxLength {
		p.indexs.popFront()
	}
}

// 执行用时 :
//20 ms , 在所有 golang 提交中击败了 97.77% 的用户
//内存消耗 :
//6.3 MB , 在所有 golang 提交中击败了 100.00% 的用户
func maxSlidingWindow(nums []int, k int) []int {
	var maxWindow []int
	list := newPriotityList(newDoubleSidedList(k), k, nums)
	list.initPush()
	if len(nums)!=0{
		maxWindow = append(maxWindow, list.PeekFrontValue())
	}

	for i := k; i < len(nums); i++ {
		list.PushIndex(i)
		maxWindow = append(maxWindow, list.PeekFrontValue())
	}
	return maxWindow
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。
根据引用\[1\],可以使用暴力解法来求解滑动窗口最大值。具体的做法是,遍历数组,对于每个窗口,使用一个内部循环来找到窗口中的最大值,并将其存储在结果数组中。时间复杂度为O(n*k),其中n为数组长度,k为窗口大小。 根据引用\[2\],还可以使用队列来求解滑动窗口最大值。具体的做法是,使用一个双端队列来维护一个单调递减的窗口。遍历数组,对于每个元素,首先判断队头是否在滑动窗口范围内,如果不在,则将其从队头移除。然后,将当前元素与队尾元素比较,如果当前元素大于队尾元素,则将队尾元素移除,直到队列为空或者当前元素小于等于队尾元素。最后,将当前元素的索引插入队尾。如果滑动窗口的元素个数达到了k个,并且始终维持在窗口中,就将队头元素加入答案数组中。时间复杂度为O(n),其中n为数组长度。 综上所述,可以使用暴力解法或者使用队列来求解leetcode滑动窗口最大值。 #### 引用[.reference_title] - *1* *3* [leetcode239. 滑动窗口最大值](https://blog.csdn.net/kkkkuuga/article/details/124829581)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [Leetcode#239. 滑动窗口最大值 (Java解法)](https://blog.csdn.net/paranior/article/details/114890555)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值