题目:
给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。
返回 滑动窗口中的最大值 。
示例 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]
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/sliding-window-maximum
思路:
本题是典型的单调栈的问题: 单调栈 or 单调队列:顾名思义,元素单调递增或者单调递减的队列 1. 构造一个队列用于存放元素队列,队首到队尾依次递减。 2. 设 窗口内的左边界的下角标为 left,窗口内的右边界为right。遍历窗口内的元素: 2.1 当队列为空时,则直接将当前元素加到队尾; 2.2 若是队列不为空,为了保持队列单调递减, 2.2.1 如果当前元素值小于等于队尾元素,则直接加到队尾; 2.2.2 如果当前元素值大于队尾元素,则弹出队尾元素,并继续判断当前元素是否小于队尾。直到队列为空或者当前元素小于队尾元素,则将当期元素加到队尾 3. 此时,队首元素为窗口内最大值,将最大值加入到结果中;窗口向右移动一位,即left与right都加1,判断队首元素的下角标index。 3.1 若是 index >= left && index <=right ,则重复2; 3.2 若是 index < left ,则说明在窗口外,先将对首元素移除队列,再重复2 4. 重复 2 与3步,直到遍历完所有元素
java代码:
class Solution {
public int[] maxSlidingWindow(int[] nums, int k) {
// 定义一个单调递减双向队列,元素为一个list,list[0] 为元素在数据的位置,list[1] 为元素的实际值
Deque<List<Integer>> queue = new LinkedList<>();
int[] result = new int[nums.length - k+1];
int index = 0;
int resultIndex = 0;
for (int left = 0, right = k - 1; right < nums.length; left++, right++) {
while (index >= left && index <= right) {
// 若是队列不为空且队首元素的index小于窗口的左边界
while (!queue.isEmpty()) {
if (queue.getFirst().get(0)<left) {
queue.removeFirst();
} else {
break;
}
}
List<Integer> subList = new ArrayList<>();
subList.add(index);
subList.add(nums[index]);
if (queue.isEmpty() || queue.getLast().get(1) >= nums[index]) {
queue.addLast(subList);
} else {
while (!queue.isEmpty()) {
if(queue.getLast().get(1)<nums[index]) {
queue.removeLast();
} else {
break;
}
}
queue.addLast(subList);
}
index++;
}
result[resultIndex++] = queue.getFirst().get(1);
}
return result;
}
}