最小\大栈的题目链接:
https://leetcode.com/submissions/detail/244382202/
可在常数时间内得到栈的最值
最小\大队列:
https://leetcode.com/problems/sliding-window-maximum/
结合最小\大栈的思路,和两个栈构成一个队列的思路完成。
平均可在常数时间内得到最值:solution using forming 2 stacks to 1 queue.
但是后面我发现了一种更简练而且效率更高的方法:单调队列(我自己的命名,可以平均线性时间得到最大\小值)。它无须借助栈,时空上都有一定程度优化(虽然仍属一个数量级):solution using max queue. 最大队列的特点是辅助Deque单调不递增,最大值在头部(微调为单调递减似乎也行)(以单调递减的索引队列[x0, x1, x2…]为例,应另外呈现规律:arr[x0+1]-arr[x1]这个区间中arr[x1]为最大值):
class MQueue {
int[] nums ;
int headi=-1,taili=-1; //to represent the queue
Deque<Integer> maxdeque = new LinkedList<Integer>();//only index
Deque<Integer> mindeque = new LinkedList<Integer>();//only index
MQueue(int[] nums){
this.nums = nums;
}
//xi = some index in array nums
public void offer(int xi) {
if( maxdeque.isEmpty()){
headi = xi;
taili = xi;
maxdeque.offer(xi);
mindeque.offer(xi);
}else{
++taili;
while(!maxdeque.isEmpty() && nums[maxdeque.peekLast()] < nums[xi]){
maxdeque.pollLast();
}
maxdeque.offer(taili);
while(!mindeque.isEmpty() && nums[mindeque.peekLast()] > nums[xi]){
mindeque.pollLast();
}
mindeque.offer(taili);
}
}
public void poll() {
++headi;
if(!maxdeque.isEmpty() && maxdeque.peek()==headi-1)
maxdeque.poll();
if(!mindeque.isEmpty() && mindeque.peek()==headi-1)
mindeque.poll();
}
public int getMax() {
return nums[maxdeque.peek()];
}
public int getMin() {
return nums[mindeque.peek()];
}
public boolean isEmpty() {
return maxdeque.isEmpty();
}
}
可进一步供练习的题目:
https://leetcode.com/problems/minimum-window-substring/
https://leetcode.com/problems/longest-substring-with-at-most-two-distinct-characters/
https://leetcode.com/problems/paint-house-ii/
Car-fleet此题也可用单调队列来解:https://leetcode.com/submissions/detail/248883712/ 理由是最终队列中包括的所有元素,都是从它的左边元素(exlusive)到它这一段中,用时最长的 (官方提供的默认解法时间复杂度与我相同)。当然此处的单调队列与上面的略有不同,在于nums[maxdeque.peekLast()].compareTo(nums[xi])<=0
其中与前峰相同时将前峰弹出了。官方由此题扩展的题目包括:
https://leetcode.com/problems/insertion-sort-list/
https://leetcode.com/problems/sort-list/
https://leetcode.com/problems/valid-anagram/