题目一: 滑动窗口的最大值。给定一个数组和滑动窗口的大小,请找出所有滑动窗口里的最大值。例如,如果输入数组{2,3,4,2,6,2,5,1}及滑动窗口的大小3,那么一共存在6个滑动窗口,他们的最大值分别为{4,4,6,6,6,5}。 数组{2,3,4,2,6,2,5,1}的滑动窗口如下:
数组中的滑动窗口 | 滑动窗口中的最大值 |
---|---|
[2,3,4],2,6,2,5,1 | 4 |
2,[3,4,2],6,2,5,1 | 4 |
2,3,[4,2,6],2,5,1 | 6 |
2,3,4,[2,6,2],5,1 | 6 |
2,3,4,2,[6,2,5],1 | 6 |
2,3,4,2,6,[2,5,1] | 5 |
解法:
/**
* 利用大小为size的大顶堆,则堆顶即为滑动窗口最大值
* @param num
* @param size
* @return
*/
public ArrayList<Integer> maxInWindows(int [] num, int size) {
ArrayList<Integer> res=new ArrayList<>();
if (size<1||size>num.length){
return res;
}
PriorityQueue<Integer> heap=new PriorityQueue<>(((o1, o2) -> o2-o1));
for (int i = 0; i <size ; i++) {
heap.add(num[i]);
}
res.add(heap.peek());
int len=num.length;
for (int i=0,j=size;j<len;i++,j++){
heap.remove(num[i]);
heap.add(num[j]);
res.add(heap.peek());
}
return res;
}
题目二: 队列的最大值。请定义一个队列并实现函数max得到队列里的最大值,要求函数max、push_back和
pop_front的时间复杂度都是O(1)。
import java.util.*;
/**
* 利用双端队列存储最大值以及可能最大值,当双端队
* 列有一个元素进队列,如果该元素大于双端队列队尾,
* 则移除队尾,直至该元素小于队尾,然后入队,若小
* 于队尾直接入队。queue存储元素,maxVal存储当前
* 最大值,以及可能的最大值
*/
public class MaxValueInQueue {
private LinkedList<Integer> queue=new LinkedList<>();
private ArrayDeque<Integer> maxVal=new ArrayDeque<>();
private void push_back(Integer val){
queue.add(val);
if (maxVal.isEmpty()){
maxVal.push(val);
}else if (val>maxVal.peekLast()){
while (!maxVal.isEmpty()&&val>maxVal.peekLast()){
maxVal.pollLast();
}
maxVal.add(val);
}else {
maxVal.add(val);
}
}
private void pop_front(){
if (queue.peek().equals(maxVal.peekFirst())){
maxVal.pollFirst();
}
queue.pop();
}
private int max(){
if (maxVal.size()>0){
return maxVal.peek();
}
return -1;
}
}
网友评论