单调队列结构?
「单调队列」这个数据结构可以解决滑动窗⼝相关的问题
难点在于如何在o(1)时间算出每个窗口中的最大值,使得整个算法在线性时间完成,特殊点在于,窗口是不断滑动的,动态地计算窗口中的最大值。
动态场景:
在一堆数字中,已知最值为A,如果给这堆数添加一个数B,那么比较一下A和B就可以立即算出新的最值
但如果减少一个数,就不能直接得到最值了,因为如果减少的这个数恰好是A,就需要遍历所有数重新找新的最值。
本题场景,每个窗口前进的时候,要添加一个数同时减少一个数,需要单调队列来辅助
滑动窗口框架
int[] maxSlidingWindow(int[] nums, int k){
MonotonicQueue window = new MonotonicQueue();
List<Integer> res = new ArrayList<>();
for(int i=0;i<nums.length;i++){
if(i < k-1){//先填满窗口的前 k-1
window.push(nums[i]);
}else{
window.push(nums[i]);//窗口向前滑动,加入新数字
res.add(window.max());//记录当前窗口的最大值
window.pop(nums[i-k+1]);//移除旧数字
}
}
//需要转成int[]数组再返回
int[] arr = new int[res.size()];
for(int i = 0; i < res.size(); i++){
arr[i] = res.get(i);
}
return arr;
}
实现单调队列数据结构
必须使用一种数据结构支持在头部和尾部进行插入和删除,双链表满足
单调队列的核心思路和单调栈类似,push方法依然在队尾添加元素,但是要把前面比自己小的元素都删掉
class MonotonicQueue{
LinkedList<Integer> q = new LinkedList<>();
public void push(int n){//在队尾添加元素 n
while(!q.isEmpty() && q.getLast() < n){//将小于n的元素全部删除
q.poollLast();
}
q.addLast(n)//然后将n加入尾部
}
public int max(){//返回当前队列中的最大值
return q.getFirst();
}
void pop(int n){//队头元素如果是n,删除它
if(n==q.getFirst()){
q.pollFirst();
}
}
}
细节问题
实现单调队列时,使用了LinkedList,链表结构支持在头部和尾部快速增删元素。
res使用ArrayList,因为后续会按照索引取元素,数组结构更合适
时间复杂度
单看push操作复杂度确实不是O(1),但是算法整体的复杂度依然是O(N)线性时间。nums中的每个元素最多被push和pop一次,没有任何多余操作
空间复杂度,就是窗口大小O(k)
标签:队列,复杂度,元素,int,最值,单调,结构 来源: https://www.cnblogs.com/autumnmoonming/p/16297775.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。