剑指 Offer 59 - I. 滑动窗口的最大值、II. 队列的最大值
剑指 Offer 59 - I. 滑动窗口的最大值
解法
使用一个双端队列,头部保存当前滑动窗口的最大值。依次将数字从尾部加入队列,如果该数字比该队列尾部数字大则将队列尾部数字去除。如果如果当前处理的数字下标与队列头部数字的下标差值大于等于3,表明该最大数字已经滑出窗口,那么删除队列头部数字。
class Solution {
public int[] maxSlidingWindow(int[] nums, int k) {
if (nums == null || nums.length == 0 || k < 1) return new int[]{};
// 使用ArrayList, LinkedList 查询太慢
List<Integer> maxInWindows = new ArrayList<>();
Deque<Integer> index = new LinkedList<>();
for (int i = 0; i < k; i++) {
while (!index.isEmpty() && nums[i] > nums[index.peekLast()])
index.pollLast();
index.offerLast(i);
}
for (int i = k; i < nums.length; ++i) {
maxInWindows.add(nums[index.peekFirst()]);
while (!index.isEmpty() && nums[i] > nums[index.peekLast()])
index.pollLast();
while(!index.isEmpty() && index.peekFirst() <= (i - k))
index.pollFirst();
index.offerLast(i);
}
maxInWindows.add(nums[index.peekFirst()]);
int[] ans = new int[maxInWindows.size()];
for (int i = 0; i < ans.length; i++) {
ans[i] = maxInWindows.get(i);
}
return ans;
}
}
剑指 Offer 59 - II. 队列的最大值
解法
与上题类似,可以使用一个双端队列保存当前队列的最大值,使用另一个队列当作普通队列。保存最大值的队列头部始终就是最大值。当普通队列弹出元素的下标与,最大值队列头部元素下标相同时,需要将最大队列的元素也去除。
class MaxQueue {
class InternalData {
int number;
int index;
InternalData(int number, int index) {
this.number = number;
this.index = index;
}
}
private int currentIndex = 0;
private Deque<InternalData> data;
private Deque<InternalData> max;
public MaxQueue() {
this.data = new LinkedList<>();
this.max = new LinkedList<>();
}
public int max_value() {
if (max.isEmpty()) return -1;
return max.peekFirst().number;
}
public void push_back(int value) {
while (!max.isEmpty() && value > max.peekLast().number)
max.pollLast();
max.offerLast(new InternalData(value, currentIndex));
data.offerLast(new InternalData(value, currentIndex));
++currentIndex;
}
public int pop_front() {
if(max.isEmpty()) return -1;
InternalData first = data.pollFirst();
if (first.index == max.peekFirst().index) {
max.pollFirst();
}
return first.number;
}
}
/**
* Your MaxQueue object will be instantiated and called as such:
* MaxQueue obj = new MaxQueue();
* int param_1 = obj.max_value();
* obj.push_back(value);
* int param_3 = obj.pop_front();
*/