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;
}
}
理解下了做法,當元素一個一個進入鏈表中時,由於是求最大值,所以比新進元素小的元素都沒有存在的必要,循環迭代會出現一個單調遞減隊列,隨着窗口的移動,最大值有可能被移除,當窗口每移動一格時,輸出鏈表的頭部,即當前窗口的最大值。