topic
You are given an array of integers nums
with a k
sliding window of size moving from the far left of the array to the far right of the array. k
You can only see numbers in the sliding window . The sliding window only moves to the right one bit at a time.
Returns the maximum value in a sliding window .
Example 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
Example 2:
输入:nums = [1], k = 1
输出:[1]
hint:
1 <= nums.length <= 10^5
-10⁴ <= nums[i] <= 104⁴
1 <= k <= nums.length
analyze
brute force
If this question is solved by brute force, it is relatively simple, but the time complexity is relatively high. Let me talk about the method of brute force first.
The number of numbers in the window is known k
, and the number of windows can be obtained according to the original array nums
and the number of numbers in the window k
, that is, the length of the returned array. The formula is: nums.length - k + 1
, enter the formula with Example 1: 8 - 3 + 1 = 6
The number of windows in Example 1 is 6 , and the number of windows in the following cycles can be used.
The number of windows is known and the possibility is known, so the number of loops in the first layer directly uses the nums.length - k + 1
result value as the judgment condition, and the loop in the second layer determines k
the maximum value of the values in the window, and takes the maximum value of each window and writes it to the return Arrays, this is the way to brute force.
code show as below:
class Solution {
public int[] maxSlidingWindow(int[] nums, int k) {
int fnum = nums.length-k+1;
int result[] = new int[fnum];
for(int i = 0; i < fnum; i++){
int max = -10001;
for(int j = i;j < k+i; j++){
if(nums[j] > max){
max = nums[j];
}
}
result[i] = max;
}
return result;
}
}
Results of the:
The time complexity of brute force cracking is O(n²)
, and the space complexity is O(1)
, and the solution of this method exceeds the time limit, so you have to use another method.
queue max
队列
Since the topic requires obtaining the maximum value of each window, use the maximum value in the subscript of the record window cycle during the loop to ensure that the queue is in order in the queue 递减队列
, so that the acquisition can be obtained 最大值
directly from 队列头
the acquisition. If 队列尾值 < 循环值
you need to transfer the queue The tail value is popped up. If the loop subscript exceeds the number of windows, the value at the head of the queue will be popped out.
Steps:
输入: nums = [1,3,-1,-3,5,3,6,7], 和 k = 3
输出: [3,3,5,5,6,7]
L-R为窗口值
初始状态:L=R=0,队列:{
}
i=0,nums[0]=1。队列为空,直接加入。队列:{
1}
i=1,nums[1]=3。队尾值为1,3>1,弹出队尾值,加入3。队列:{
3}
i=2,nums[2]=-1。队尾值为3,-1<3,直接加入。队列:{
3,-1}。此时窗口已经形成,L=0,R=2,result=[3]
i=3,nums[3]=-3。队尾值为-1,-3<-1,直接加入。队列:{
3,-1,-3}。队首3对应的下标为1,L=1,R=3,有效。result=[3,3]
i=4,nums[4]=5。队尾值为-3,5>-3,依次弹出后加入。队列:{
5}。此时L=2,R=4,有效。result=[3,3,5]
i=5,nums[5]=3。队尾值为5,3<5,直接加入。队列:{
5,3}。此时L=3,R=5,有效。result=[3,3,5,5]
i=6,nums[6]=6。队尾值为3,6>3,依次弹出后加入。队列:{
6}。此时L=4,R=6,有效。result=[3,3,5,5,6]
i=7,nums[7]=7。队尾值为6,7>6,弹出队尾值后加入。队列:{
7}。此时L=5,R=7,有效。result=[3,3,5,5,6,7]
code show as below:
public int[] maxSlidingWindow(int[] nums, int k) {
ArrayDeque<Integer> deque = new ArrayDeque<Integer>();
int result[] = new int[nums.length-k+1];
for (int i = 0; i < nums.length; i++) {
// 判断值是否比尾部值大,大的话将队列的尾部值退出
while (!deque.isEmpty() && nums[i] >= nums[deque.peekLast()]) {
deque.pollLast();
}
deque.addLast(i);
// 超出窗口的值退出队列
if(deque.peek() <= i-k){
deque.poll();
}
// 前面n-1不参与数组写入
if(i+1 >= k){
result[i+1-k] = nums[deque.peek()];
}
}
return result;
}
Results of the:
The time complexity of this method isO(n)