一、滑动窗口最大值
- 题目描述:给定一个数组
nums
,有一个大小为k
的滑动窗口从数组的最左端移动到最右端。你只可以看到在滑动窗口内的k
个数字。滑动窗口每次只向右移动一位。返回滑动窗口中的最大值。 - 例如:输入:
nums = [1,3,-1,-3,5,3,6,7]
,k = 3
,输出:[3,3,5,5,6,7]
。
解题思路:
- 使用一个双端队列来存储可能成为滑动窗口最大值的元素的索引。
- 遍历数组:
- 当队列不为空且当前元素大于等于队列尾部元素所对应的数组值时,将队列尾部元素弹出,确保队列始终保持单调递减。
- 将当前元素的索引加入队列。
- 如果窗口已经形成(即当前索引大于等于
k - 1
),将队列头部元素对应的数组值加入结果列表,因为队列头部元素对应的数组值是当前窗口中的最大值。 - 如果队列头部元素的索引已经不在当前窗口内(即队列头部元素的索引小于等于当前索引减去
k
),将队列头部元素弹出。
- 最后将结果列表转换为数组返回。
C++ 代码:
#include <iostream>
#include <vector>
#include <deque>
using namespace std;
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
vector<int> result;
deque<int> dq;
for (int i = 0; i < nums.size(); ++i) {
while (!dq.empty() && nums[i] >= nums[dq.back()])
dq.pop_back();
dq.push_back(i);
if (i >= k - 1)
result.push_back(nums[dq.front()]);
if (dq.front() <= i - k + 1)
dq.pop_front();
}
return result;
}
Java 代码:
import java.util.ArrayList;
import java.util.Deque;
import java.util.LinkedList;
import java.util.List;
class Solution {
public int[] maxSlidingWindow(int[] nums, int k) {
List<Integer> result = new ArrayList<>();
Deque<Integer> dq = new LinkedList<>();
for (int i = 0; i < nums.length; i++) {
while (!dq.isEmpty() && nums[i] >= nums[dq.peekLast()]) {
dq.pollLast();
}
dq.addLast(i);
if (i >= k - 1) {
result.add(nums[dq.peekFirst()]);
}
if (dq.peekFirst() <= i - k + 1) {
dq.pollFirst();
}
}
int[] arr = new int[result.size()];
for (int i = 0; i < result.size(); i++) {
arr[i] = result.get(i);
}
return arr;
}
}
Go 代码:
package main
import "fmt"
func maxSlidingWindow(nums []int, k int) []int {
result := make([]int, 0)
deque := make([]int, 0)
for i := 0; i < len(nums); i++ {
// 保持单调递减队列
for len(deque) > 0 && nums[i] >= nums[deque[len(deque)-1]] {
deque = deque[:len(deque)-1]
}
deque = append(deque, i)
if i >= k-1 {
result = append(result, nums[deque[0]])
}
if deque[0] <= i-k+1 {
deque = deque[1:]
}
}
return result
}
你可以使用以下方式调用这个函数:
func main() {
nums := []int{1, 3, -1, -3, 5, 3, 6, 7}
k := 3
fmt.Println(maxSlidingWindow(nums, k))
}