描述:
Given an array A and an integer K. Find the maximum for each and every contiguous subarray of size K.
Input: The first line of input contains an integer T denoting the number of test cases. The first line of each test case contains a single integer N denoting the size of array and the size of subarray K. The second line contains N space-separated integers A1, A2, ..., AN denoting the elements of the array.
Output: Print the maximum for every subarray of size k.
Constraints: 1 ≤ T ≤ 200 1 ≤ N ≤ 107 1 ≤ K ≤ N 0 ≤ A[i] <= 107
Example: Input: 2 9 3 1 2 3 1 4 5 2 3 6 10 4 8 5 10 7 9 4 15 12 90 13
Output: 3 3 4 5 5 5 6 10 10 10 15 15 90 90
Explanation: Testcase 1: Starting from first subarray of size k = 3, we have 3 as maximum. Moving the window forward, maximum element are as 3, 4, 5, 5, 5 and 6.
这个题目看描述也知道,典型的滑动窗口题目,就是给个窗口大小k,然后在这个序列上滑动,取该窗口的最大元素然后输出。
思路:
我们用双端队列维护这个窗口内的所有的候选输出,也就是说我们每次都倾向于把大的排在双端队列的队头,比如某时刻窗口内序列为3,2,1,那么当窗口滑动到下一个后,最大的3脱离窗口,此时2成为output的第一候选数。
而如果某时刻窗口内为1,2,3,那么我们应该维护双端队列中3放到队头,把1,2都删掉,因为如果不这么做,双端队列直接输出队头1为output,而1不是[1,2,3]中最大的。
总而言之,我们构建这样一个双端队列,每次都让窗口内最大的元素放在队首,也就是本次窗口要输出的最大值,然后滑动一步窗口,判断此时队首元素会不会脱离窗口,如果脱离,那么让它出队,后面的元素顶上来,成为要输出最大的候选数。
代码:
import java.util.*;
import java.io.*;
import java.lang.*;
class Solution{
static int arr[] = new int [10000000];
public static void main(String args[]){
Scanner sc = new Scanner(System.in);
int t = sc.nextInt();
while(t-->0){
int n = sc.nextInt();
int k = sc.nextInt();
for(int i=0;i<n;i++){
arr[i]=sc.nextInt();
}
max_of_subarrays(n,k);
}
}
static void max_of_subarrays(int n,int k){
Deque<Integer> dq = new LinkedList<>();
StringBuilder sb = new StringBuilder();
int i=0;
for(i=0;i<k;i++){
while(dq.isEmpty()==false&&arr[i]>=arr[dq.peekLast()])
dq.pollLast();
dq.addLast(i);
}
for(;i<n;i++){
sb.append(arr[dq.peekFirst()]+" ");
while(dq.isEmpty()==false&&dq.peekFirst()<=i-k)
dq.pollFirst();
while(dq.isEmpty()==false&&arr[i]>=arr[dq.peekLast()]){
dq.pollLast();
}
dq.addLast(i);
}
sb.append(arr[dq.peekFirst()]);
dq.pollFirst();
System.out.println(sb);
}
}