题目描述
有一个整型数组arr和一个大小为w的窗口从数组的最左边滑到最右边,窗口每次向右边滑一个位置,求每一种窗口状态下的最大值。(如果数组长度为n,窗口大小为w,则一共产生n-w+1个窗口的最大值)
输入描述:
第一行输入n和w,分别代表数组长度和窗口大小
第二行输入n个整数XiX_iXi,表示数组中的各个元素
输出描述:
输出一个长度为n-w+1的数组res,res[i]表示每一种窗口状态下的最大值
示例1
输入
8 3
4 3 5 4 3 3 6 7
输出
5 5 5 4 6 7
说明
例如,数组为[4,3,5,4,3,3,6,7],窗口大小为3时:
[4 3 5] 4 3 3 6 7 窗口中最大值为5
4 [3 5 4] 3 3 6 7 窗口中最大值为5
4 3 [5 4 3] 3 6 7 窗口中最大值为5
4 3 5 [4 3 3] 6 7 窗口中最大值为4
4 3 5 4 [3 3 6] 7 窗口中最大值为6
4 3 5 4 3 [3 6 7] 窗口中最大值为7
输出的结果为{5 5 5 4 6 7}
解法一:利用堆(超时了)
import java.io.*;
import java.util.*;
public class Main{
public static void main(String[] args) throws IOException{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String[] ss = br.readLine().trim().split(" ");
int len = Integer.parseInt(ss[0]);
int win = Integer.parseInt(ss[1]);
ss = br.readLine().trim().split(" ");
int[] arr = new int[len];
for(int i=0;i<len;i++){
arr[i] = Integer.parseInt(ss[i]);
}
String result = func(arr,len,win);
System.out.println(result);
}
public static String func(int[] arr,int len,int win){
PriorityQueue<Integer> pq = new PriorityQueue(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2-o1;
}
});
int i=0;
StringBuilder sb = new StringBuilder();
for(;i<win&&i<len;i++){
pq.add(arr[i]);
}
sb.append(pq.peek());
for(;i<len;i++){
pq.remove(arr[i-win]);
pq.add(arr[i]);
sb.append(" "+pq.peek());
}
return sb.toString();
}
}
解法二:双端队列
import java.io.*;
import java.util.*;
public class Main{
public static void main(String[] args) throws IOException{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String[] ss = br.readLine().trim().split(" ");
int len = Integer.parseInt(ss[0]);
int win = Integer.parseInt(ss[1]);
ss = br.readLine().trim().split(" ");
int[] arr = new int[len];
for(int i=0;i<len;i++){
arr[i] = Integer.parseInt(ss[i]);
}
String result = func(arr,len,win);
System.out.println(result);
}
public static String func(int[] arr,int len,int w){
if(arr==null||w<1||w>len){
return "";
}
LinkedList<Integer> list = new LinkedList<>();
StringBuilder sb = new StringBuilder();
for(int i=0;i<len;i++){
//这里是先加入还是先去除第一个都是可以的
while(!list.isEmpty()&&arr[list.peekLast()]<=arr[i]){
list.pollLast();
}
list.addLast(i);
if(list.peekFirst()==i-w){
list.pollFirst();
}
if(i==w-1){
sb.append(arr[list.peekFirst()]);
}else if(i>w-1){
sb.append(" "+arr[list.peekFirst()]);
}
}
return sb.toString();
}
}