给定一个数组和滑动窗口的大小,找出所有滑动窗口里数值的最大值。例如,如果输入数组{2,3,4,2,6,2,5,1}及滑动窗口的大小3,那么一共存在6个滑动窗口,他们的最大值分别为{4,4,6,6,6,5}; 针对数组{2,3,4,2,6,2,5,1}的滑动窗口有以下6个: {[2,3,4],2,6,2,5,1}, {2,[3,4,2],6,2,5,1}, {2,3,[4,2,6],2,5,1}, {2,3,4,[2,6,2],5,1}, {2,3,4,2,[6,2,5],1}, {2,3,4,2,6,[2,5,1]}。
/*
维护一个队列: 队列的头部始终是当前窗口中的最大值的索引
*/
class Solution {
public int[] maxSlidingWindow(int[] nums, int k) {
//假设窗口长度大于等于k并且k大于0; 没通过特殊案例:[], 0
if(nums==null || nums.length==0 || k==0)
return new int[]{};
//
LinkedList<Integer> queue = new LinkedList<>();
int n = nums.length;
int[] res = new int[n-k+1];
int index=0;
for(int i=0; i<n; i++){
int cur = nums[i];
while(!queue.isEmpty() && cur>nums[queue.getLast()]){
queue.pollLast();
}
//here, queue.isEmpty() || cur<=queue.getLast()
queue.add(i);
//更新res之前需要检查队列头部元素是否过期; 如果过期则删除
if(i-queue.peek()>=k){
queue.poll();
}
//如果窗口大小达到k则更新res;
if(i+1>=k){
res[index++] = nums[queue.peek()];
}
}
return res;
}
}
import java.util.ArrayList;
import java.util.LinkedList;
public class Solution {
public ArrayList<Integer> maxInWindows(int [] num, int size)
{
ArrayList<Integer> res = new ArrayList<>();
if(num==null || num.length==0 || size < 1)
return res;
LinkedList<Integer> ll = new LinkedList<>();
for(int i=0; i<num.length; i++){
//队列中存储索引, 方便判断队列中的元素是否超出滑窗大小
//队列为空
if(ll.isEmpty())
ll.add(i);
//队列不为空
else{
//队列不为空,且当前元素大于队尾索引对应的元素, 则去掉队尾, 直到队列为空或者当前元素小于队尾索引对应的元素
while(!ll.isEmpty() && num[i]>num[ll.getLast()])
ll.removeLast();
ll.add(i);
//如果队尾索引减去队首索引加1大于滑窗长度,说明队首元素不在滑窗内了,去掉队首元素
if(ll.getLast() - ll.getFirst() + 1 > size)
ll.removeFirst();
}
//i大于等于滑窗长度减1时滑窗才是满的
if(i >= size-1)
//队列中存的是索引! res中需要加入的是索引对应的元素!
res.add(num[ll.peek()]);
}
return res;
}
}
import java.util.LinkedList;
import java.util.ArrayList;
public class Solution {
public ArrayList<Integer> maxInWindows(int [] num, int size)
{
LinkedList<Integer> deque = new LinkedList<>();
ArrayList<Integer> res = new ArrayList<>();
//input check
//size<=0也是特殊情况,要小心
if(num==null || num.length==0 || size<=0)
return res;
for(int i=0; i<num.length; i++){
//队列为空,直接加入元素即可
if(deque.isEmpty())
deque.add(i);
//队列不为空,就存在比较关系了
else{
while(!deque.isEmpty() && num[i] > num[deque.peekLast()]){
deque.pollLast();
}
deque.add(i);
}
//判断队列首尾元素距离
if(deque.peekLast() - deque.peek()>=size)
deque.poll();
//当前轮次滑动窗口的最大值
if(i>=size-1)
res.add(num[deque.peek()]);
}
return res;
}
}
import java.util.ArrayList;
import java.util.ArrayDeque;
public class Solution {
public ArrayList<Integer> maxInWindows(int [] num, int size)
{
ArrayList<Integer> al = new ArrayList<Integer>();
//input check
if(num.length<1 || num.length<size || size < 1)
return al;
//execute
int lower_bound;
ArrayDeque<Integer> ad = new ArrayDeque<Integer>();
for(int i=0; i<num.length; i++){
lower_bound = i - size + 1; //如果队列中的头元素小于lower_bound,就得把头元素删掉
//队列为空则添加元素
if(ad.isEmpty())
ad.add(i);
else{ // 队列不为空,则向队尾添加元素, 添加之前需要判断是否删除队列中的元素
while(!ad.isEmpty() && num[i]>num[ad.getLast()]) // 访问队列中的元素时要确保队列不为空
ad.pollLast();
ad.add(i);
}
while(!ad.isEmpty() && ad.getFirst()<lower_bound)//如果队首元素小于lower_bound,说明队首元素不在当前滑窗的范围中,需要删除队首元素
ad.pollFirst();
if(lower_bound>=0)
al.add(num[ad.getFirst()]);
}
return al;
}
}
请定义一个队列并实现函数 max_value 得到队列里的最大值,要求函数max_value、push_back 和 pop_front 的时间复杂度都是O(1)。
若队列为空,pop_front 和 max_value 需要返回 -1
示例 1:
输入:
["MaxQueue","push_back","push_back","max_value","pop_front","max_value"]
[[],[1],[2],[],[],[]]
输出: [null,null,null,2,1,2]
示例 2:
输入:
["MaxQueue","pop_front","max_value"]
[[],[],[]]
输出: [null,-1,-1]
class MaxQueue {
//存储入队元素
private LinkedList<Integer> queue1;
//存当前队列中的最大值
private LinkedList<Integer> queue2;
public MaxQueue() {
queue1 = new LinkedList<>();
queue2 = new LinkedList<>();
}
public int max_value() {
return queue2.isEmpty()? -1 : queue2.peek();
}
public void push_back(int value) {
queue1.add(value);
//不等式不能取等, 为了让等于队尾元素的值入队
while(!queue2.isEmpty() && value > queue2.getLast()){
queue2.pollLast();
}
queue2.add(value);
}
public int pop_front() {
if(queue1.isEmpty())
return -1;
int cur = queue1.pop();
if(cur == queue2.peek())
queue2.poll();
return cur;
}
}