@@ -51,7 +51,7 @@ public class MaxInWindow {
5151
5252 ......
5353
54- 再看最后一个元素1 ,它入列前,队列中有6和5,且6位于队列头是窗口中的最大值,按照之前的做法,应该将1入列,但是窗口的大小为3,此时队列头的6已经在窗口之外了,所以要讲6从队列中弹出 ,那么此时队列中还剩下5和1且5位于队列头,所以最后一个窗口中的最大值是5。** 那么如何判断某个元素还在不在窗口内呢?我们应该在往队列中存元素的下标而不是元素本身。 ** 若当前正访问的元素的下标与窗口最大值的下标(即队列头元素的下标)超过了窗口的宽度,就应该从队列头删除这个在滑动窗口之外的最大值。
54+ 如果还有最后一个元素1 ,它入列前,队列中有6和5,且6位于队列头是窗口中的最大值,按照之前的做法,应该将1入列,但是窗口的大小为3,此时队列头的6已经在窗口之外了,所以要将6从队列中弹出 ,那么此时队列中还剩下5和1且5位于队列头,所以最后一个窗口中的最大值是5。** 那么如何判断某个元素还在不在窗口内呢?我们应该在往队列中存元素的下标而不是元素本身** 。 若当前正访问的元素的下标与窗口最大值的下标(即队列头元素的下标)超过了窗口的宽度,就应该从队列头删除这个在滑动窗口之外的最大值。
5555
5656总之就是:
5757
@@ -91,55 +91,56 @@ public class MaxInWindow {
9191> 定义一个队列,实现max方法得到队列中的最大值。要求入列、出列以及邱最大值的方法时间复杂度都是O(1)
9292> ```
9393
94- 此题和面试题30“包含min的栈”同一个思路。
9594
96- 一个dataQueue正常入列、出列元素,为了以O(1)的时间获取当前队列的最大值,需要使用一个maxQueue存放当前队列中最大值。具体来说就是,**如果即将要存入的元素比当前最大值还大,那么存入这个元素;否则再次存入当前最大值。**
95+ 思路和上题类似。
96+
97+ 使用一个辅助队列(双端队列),队列头记录最大值,队列中的元素是单调递减的。
98+
99+ - 即将要入列的的元素比队列中哪些元素大,就将那些元素先从队列中删除,然后入列新元素;
100+ - 出列时,如果弹出的元素和辅助队列的队列头值一致,则辅助队列也需要弹出该值。
97101
98102```java
99- package Chap6;
103+ class MaxQueue {
100104
101- import java.util.Deque ;
102- import java.util.LinkedList ;
105+ private Queue<Integer> queue ;
106+ private Deque<Integer> maxQueue ;
103107
104- public class MaxQueue {
105- private Deque<Integer> maxDeque = new LinkedList<>();
106- private Deque<Integer> dataDeque = new LinkedList<>();
107108
108- public void offer(int number) {
109- dataDeque.offerLast(number);
110- // 即将要存入的元素比当前队列最大值还大,存入该元素
111- if (maxDeque.isEmpty() || number > maxDeque.peekFirst()) maxDeque.offerFirst(number);
112- // 即将要存入的元素不超过当前队列最大值,再将最大值存入一次
113- else maxDeque.offerFirst(maxDeque.peekFirst());
109+ public MaxQueue() {
110+ queue = new LinkedList<>();
111+ maxQueue = new LinkedList<>();
114112 }
115113
116- public void poll() {
117- if (dataDeque.isEmpty()) throw new RuntimeException("队列已空");
118- dataDeque.pollFirst();
119- maxDeque.pollFirst();
114+ public int max_value() {
115+ if (maxQueue.isEmpty()) {
116+ return -1;
117+ }
118+ return maxQueue.peekFirst();
120119 }
121120
122- public int max() {
123- if (maxDeque.isEmpty()) throw new RuntimeException("队列已空");
124- return maxDeque.peekFirst();
125- }
126- }
121+ public void push_back(int value) {
122+ queue.offer(value);
123+ while (!maxQueue.isEmpty() && value > maxQueue.peekLast()) {
124+ maxQueue.pollLast();
125+ }
126+ maxQueue.offerLast(value);
127127
128- ```
128+ }
129129
130- 还是上面的例子{2, 3, 4, 2, 6, 2, 5},分析随着各个元素入列dataQueue和maxQueue的情况。
130+ public int pop_front() {
131+ if (queue.isEmpty()) {
132+ return -1;
133+ }
134+ int tmp = queue.poll();
135+ if (tmp == maxQueue.peekFirst()) {
136+ maxQueue.pollFirst();
137+ }
138+ return tmp;
139+ }
131140
132- | 操作 | dataQueue | maxQueue | max |
133- | ---- | ------------------- | ------------------- | ---- |
134- | 2入列 | 2 | 2 | 2 |
135- | 3入列 | 2, 3 | 3, 2 | 3 |
136- | 4入列 | 2, 3, 4 | 4, 3, 2 | 4 |
137- | 2入列 | 2, 3, 4, 2 | 4, 4, 3, 2 | 4 |
138- | 6入列 | 2, 3, 4, 2, 6 | 6, 4, 4, 3, 2 | 6 |
139- | 2入列 | 2, 3, 4, 2, 6, 2 | 6, 6, 4, 4, 3, 2 | 6 |
140- | 5入列 | 2, 3, 4, 2, 6, 2, 5 | 6, 6, 6, 4, 4, 3, 2 | 6 |
141+ }
141142
142- 出列的话两个队列同时出列一个元素,保证了maxQueue的队列头元素始终是dataQueue的当前最大值。
143+ ```
143144
144145---
145146
0 commit comments