Given an array nums, there is a sliding window of size k which is moving from the very left of the array to the very right. You can only see the k numbers in the window. Each time the sliding window moves right by one position. Return the max sliding window.
Example:
Input: nums =[1,3,-1,-3,5,3,6,7]
, and k = 3 Output:[3,3,5,5,6,7] Explanation:
Window position Max --------------- ----- [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
Note:
You may assume k is always valid, 1 ≤ k ≤ input array's size for non-empty array.
Follow up:
Could you solve it in linear time?
Idea 1. Sliding window, borrow the idea of montone increasing queue, moving two pointers.
右边界向右边滑,扫新的元素,
- pop out all nums[j] if nums[right] > nums[j] (j < i), 因为新的数大,窗口中前面的小数不可能是窗口的max value, 形成一个递减的queue, the queue head is the local maximum in the current window;
- push nums[right]
左边界向右边滑,
pop out nums[left] if deque.peekFirst == nums[left], 如果左边界是最大值,向右移左边届已经不在有效窗口内,需要从queue头移除最大值
Since pop operation needed on both ending, deque is a suitable struct.
Time complexity: O(n) since each element is only pushed once and poped out once from the deque.
Space complexity: O(n)
1.a deque store the array item
1 class Solution { 2 public int[] maxSlidingWindow(int[] nums, int k) { 3 if(nums.length == 0 || k > nums.length) { 4 return new int[0]; 5 } 6 7 Deque<Integer> maxBuffer = new LinkedList<>(); 8 int[] result = new int[nums.length - k + 1]; 9 10 for(int left = 0, right = 0; right < nums.length; ++right) { 11 while(!maxBuffer.isEmpty() && nums[right] > maxBuffer.peekLast()) { 12 maxBuffer.pollLast(); 13 } 14 maxBuffer.offerLast(nums[right]); 15 if(right >= k-1) { 16 result[left] = maxBuffer.peekFirst(); 17 if(nums[left] == result[left]) { 18 maxBuffer.pollFirst(); 19 } 20 ++left; 21 } 22 } 23 24 return result; 25 } 26 }
python
1 class Solution: 2 def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]: 3 maxBuffer = collections.deque() 4 5 result = [] 6 for right in range(len(nums)): 7 while maxBuffer and maxBuffer[-1] < nums[right]: 8 maxBuffer.pop() 9 10 maxBuffer.append(nums[right]) 11 if right >= k - 1: 12 result.append(maxBuffer[0]) 13 14 if maxBuffer[0] == nums[right - k + 1]: 15 maxBuffer.popleft() 16 17 return result
1.b deque store the array index, instead,
1 class Solution { 2 public int[] maxSlidingWindow(int[] nums, int k) { 3 if(nums.length == 0 || k > nums.length) { 4 return new int[0]; 5 } 6 7 int[] result = new int[nums.length - k + 1]; 8 Deque<Integer> maxIndexBuffer = new ArrayDeque(); 9 for(int left = 0, right = 0; right < nums.length; ++right) { 10 while(!maxIndexBuffer.isEmpty() && nums[maxIndexBuffer.peekLast()] < nums[right] ) { 11 maxIndexBuffer.pollLast(); 12 } 13 maxIndexBuffer.offerLast(right); 14 15 if(right >= k-1) { 16 int maxIndex = maxIndexBuffer.peekFirst(); 17 result[left] = nums[maxIndex]; 18 19 if(maxIndex == left) { 20 maxIndexBuffer.pollFirst(); 21 } 22 ++left; 23 } 24 } 25 26 return result; 27 } 28 }
python
1 class Solution: 2 def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]: 3 maxIndex = collections.deque() 4 5 result = [] 6 for right in range(len(nums)): 7 while maxIndex and nums[maxIndex[-1]] < nums[right]: 8 maxIndex.pop() 9 10 maxIndex.append(right) 11 if right >= k - 1: 12 result.append(nums[maxIndex[0]]) 13 14 if maxIndex[0] == right - k + 1: 15 maxIndex.popleft() 16 17 return result