Skip to content

Commit 59205b8

Browse files
authored
Update 剑指offer面试题59--队列的最大值.md
修复“队列的最大值”错误
1 parent a3a7e1b commit 59205b8

File tree

1 file changed

+37
-36
lines changed

1 file changed

+37
-36
lines changed

notes/剑指offer面试题59--队列的最大值.md

Lines changed: 37 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)