1.题目
给定一个数组 nums 和滑动窗口的大小 k,请找出所有滑动窗口里的最大值。
示例:
输入: 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
提示:
你可以假设 k 总是有效的,在输入数组不为空的情况下,1 ≤ k ≤ 输入数组的大小。
注意:本题与主站 239 题相同:https://leetcode-cn.com/problems/sliding-window-maximum/
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/hua-dong-chuang-kou-de-zui-da-zhi-lcof
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
2.思路
感觉没什么好的思路,主要就是比较前k个中最大的那个,然后出栈一下,再比较前k个最大的那个,第一次比较的结果很有用,后续的比较需要依赖第一次比较的结果,然后数组其实是和队列一样的是先进先出,然后还要比较当前队列的最大值,然后我结合了化栈为队和栈获取最大值的自定义实现写的。。。
3.coding
class Solution {
public int[] maxSlidingWindow(int[] nums, int k) {
if(nums.length == 0){
return new int[]{};
}
int[] maxs = new int[nums.length - k + 1];
MyQueue myQueue = new MyQueue();
for (int i = 0; i + k <= nums.length; i++) {
if (i == 0) {
for (int j = 0; j < k; j++) {
myQueue.push(nums[j]);
}
} else {
myQueue.pop();
myQueue.push(nums[i + k - 1]);
}
maxs[i] = myQueue.getMax();
}
return maxs;
}
class MyQueue {
MaxStack popStack = new MaxStack();
MaxStack pushStack = new MaxStack();
/**
* Initialize your data structure here.
*/
public MyQueue() {
}
/**
* Push element x to the back of queue.
*/
public void push(int x) {
pushStack.push(x);
}
/**
* Removes the element from in front of queue and returns that element.
*/
public int pop() {
transtion();
return popStack.pop();
}
private void transtion() {
if (popStack.isEmpty()) {
while (!pushStack.isEmpty()) {
popStack.push(pushStack.pop());
}
}
}
/**
* Get the front element.
*/
public int peek() {
transtion();
return popStack.peek();
}
/**
* Returns whether the queue is empty.
*/
public boolean empty() {
return popStack.isEmpty() && pushStack.isEmpty();
}
public int getMax() {
if (popStack.isEmpty()) {
return pushStack.getMax();
} else if (pushStack.isEmpty()) {
return popStack.getMax();
} else {
return popStack.getMax() > pushStack.getMax() ? popStack.getMax() : pushStack.getMax();
}
}
}
class MaxStack {
Stack<Integer> stack = new Stack();
Stack<Integer> maxStack = new Stack();
/**
* initialize your data structure here.
*/
public MaxStack() {
}
public void push(int x) {
stack.push(x);
if (maxStack.isEmpty()) {
maxStack.push(x);
} else if (x >= maxStack.peek()) {
maxStack.push(x);
}
}
public int pop() {
if (!stack.isEmpty()) {
int x = stack.pop();
if (x == maxStack.peek()) {
maxStack.pop();
}
return x;
}
throw new RuntimeException("pop for none");
}
public int peek() {
return stack.peek();
}
public int getMax() {
return maxStack.peek();
}
public boolean isEmpty() {
return stack.isEmpty();
}
}
}
看解答发现这题对应于hard难度,你这简单难度对应hard难度还玩不玩啊。。。我说怎么这么难写
注意:本题与主站 239 题相同:https://leetcode-cn.com/problems/sliding-window-maximum/
参考答案
class Solution {
public int[] maxSlidingWindow(int[] nums, int k) {
if(nums == null || nums.length == 0 || k == 0){
return new int[0];
}
LinkedList<Integer> linkedList = new LinkedList<Integer>();
int[] res = new int[nums.length - k + 1];
for(int i = 0; i < nums.length; i++) {
while (!linkedList.isEmpty()
&& nums[i] > nums[linkedList.peekLast()]) {
linkedList.removeLast();
}
linkedList.add(i);
if (i - k >= 0 && linkedList.getFirst() == i - k){
linkedList.removeFirst();
}
if (i - k + 1 >= 0){
res[i - k + 1] = nums[linkedList.getFirst()];
}
}
return res;
}
}
理解下了做法,当元素一个一个进入链表中时,由于是求最大值,所以比新进元素小的元素都没有存在的必要,循环迭代会出现一个单调递减队列,随着窗口的移动,最大值有可能被移除,当窗口每移动一格时,输出链表的头部,即当前窗口的最大值。