目录


239. 滑动窗口最大值 Sliding Window Maximum
numskk

返回 滑动窗口中的最大值 

示例 1:

输入:nums = [1,3,-1,-3,5,3,6,7], k = 3
输出:[3,3,5,5,6,7]
解释:
 滑动窗口的位置                最大值
---------------               -----
[1  3  -1] -3  5  3  6  7       3
 1 [3  -1  -3] 5  3  6  7       3
 1  3 [-1  -3  5] 3  6  7       5
 1  3  -1 [-3  5  3] 6  7       5
 1  3  -1  -3 [5  3  6] 7       6
 1  3  -1  -3  5 [3  6  7]      7

示例 2:

输入:nums = [1], k = 1
输出:[1]

提示:

1 <= nums.length <= 10^5-10^4 <= nums[i] <= 10^41 <= k <= nums.length

代码1: 暴力枚举

package main

import "fmt"

func maxSlidingWindow(nums []int, k int) []int {
	ans := make([]int, len(nums)-k+1)
	for i := 0; i <= len(nums)-k; i++ {
		max := nums[i]
		for j := i + 1; j < i+k; j++ {
			if nums[j] > max {
				max = nums[j]
			}
		}
		ans[i] = max
	}
	return ans
}

func main() {
	nums := []int{1, 3, -1, -3, 5, 3, 6, 7}
	k := 3
	fmt.Println(maxSlidingWindow(nums, k))
	nums = []int{1}
	k = 1
	fmt.Println(maxSlidingWindow(nums, k))
}

代码2: 双端队列

package main

import "fmt"

func maxSlidingWindow(nums []int, k int) []int {
	var ans []int
	q := make([]int, 0) // 双端队列,存放的是数字的下标
	for i, num := range nums {
		if len(q) > 0 && q[0] < i-k+1 {
			// 当前滑动窗口的左端已离队列滑出,则要将该元素从队列中弹出
			q = q[1:]
		}
		// 将当前数字与双端队列队尾数字比较,如果当前数字大于队列数字,则弹出队列。
		// 这是因为当前数字更大,而队列中以前数字已经没有用处,我们可以弹出它们。
		for len(q) > 0 && nums[q[len(q)-1]] < num {
			q = q[:len(q)-1]
		}
		// 将当前数字下标加入队列
		q = append(q, i)
		// 到了一个滑动窗口的结束,将当前窗口中的最大值加入结果集中
		if i >= k-1 {
			ans = append(ans, nums[q[0]])
		}
	}
	return ans
}

func main() {
	nums := []int{1, 3, -1, -3, 5, 3, 6, 7}
	k := 3
	fmt.Println(maxSlidingWindow(nums, k))
	nums = []int{1}
	k = 1
	fmt.Println(maxSlidingWindow(nums, k))
}

代码: 动态规划

package main

import "fmt"

func maxSlidingWindow(nums []int, k int) []int {
	n := len(nums)
	leftMax := make([]int, n)
	rightMax := make([]int, n)
	// 计算leftMax数组
	for i := 0; i < n; i++ {
		if i%k == 0 {
			leftMax[i] = nums[i]
		} else {
			leftMax[i] = max(leftMax[i-1], nums[i])
		}
	}
	// 计算rightMax数组
	for i := n - 1; i >= 0; i-- {
		if i == n-1 || (i+1)%k == 0 {
			rightMax[i] = nums[i]
		} else {
			rightMax[i] = max(rightMax[i+1], nums[i])
		}
	}
	// 获取每个窗口的最大值
	ans := make([]int, n-k+1)
	for i := 0; i <= n-k; i++ {
		ans[i] = max(rightMax[i], leftMax[i+k-1])
	}
	return ans
}

func max(x, y int) int {
	if x > y {
		return x
	}
	return y
}

func main() {
	nums := []int{1, 3, -1, -3, 5, 3, 6, 7}
	k := 3
	fmt.Println(maxSlidingWindow(nums, k))
	nums = []int{1}
	k = 1
	fmt.Println(maxSlidingWindow(nums, k))
}

输出:

[3 3 5 5 6 7]

[1]


480. 滑动窗口中位数 Sliding Window Median

中位数是有序序列最中间的那个数。如果序列的长度是偶数,则没有最中间的数;此时中位数是最中间的两个数的平均数。

例如:

[2,3,4]3[2,3](2 + 3) / 2 = 2.5

给你一个数组 nums,有一个长度为 k 的窗口从最左端滑动到最右端。窗口中有 k 个数,每次窗口向右移动 1 位。你的任务是找出每次窗口移动后得到的新窗口中元素的中位数,并输出由它们组成的数组。

示例:

[1,3,-1,-3,5,3,6,7]
 窗口位置                      中位数
---------------               -----
[1  3  -1] -3  5  3  6  7       1
 1 [3  -1  -3] 5  3  6  7      -1
 1  3 [-1  -3  5] 3  6  7      -1
 1  3  -1 [-3  5  3] 6  7       3
 1  3  -1  -3 [5  3  6] 7       5
 1  3  -1  -3  5 [3  6  7]      6
[1,-1,-1,3,5,6]

提示:

kk10^-5

代码: 暴力枚举

package main

import (
	"fmt"
	"sort"
)

func medianSlidingWindow(nums []int, k int) []float64 {
	n := len(nums)
	if k == 1 {
		ans := make([]float64, n)
		for i := 0; i < n; i++ {
			ans[i] = float64(nums[i])
		}
		return ans
	}
	ans := make([]float64, n-k+1)
	for i := 0; i <= n-k; i++ {
		tmp := make([]int, k)
		copy(tmp, nums[i:i+k])
		sort.Ints(tmp)
		if k%2 == 0 {
			ans[i] = float64(tmp[k/2-1]+tmp[k/2]) / 2
		} else {
			ans[i] = float64(tmp[k/2])
		}
	}
	return ans
}

func main() {
	nums := []int{1, 3, -1, -3, 5, 3, 6, 7}
	k := 3
	fmt.Println(medianSlidingWindow(nums, k))
}

输出:

[1 -1 -1 3 5 6]


持续,努力奋斗做强刷题搬运工!

👍 点赞,你的认可是我坚持的动力! 

🌟 收藏,你的青睐是我努力的方向! 

评论,你的意见是我进步的财富!  

(2023.5.16~)更新中...

(2023.3.11~)更新中...

(2023.2.18~2023.5.18)暂停更

(2023.2.18~2023.5.18)暂停更

(2023.3.11~2023.5.18)暂停更