雙端隊列題解
239. 滑動窗口最大值
方法一:暴力法
該題最直接的解法,直接遍歷每個滑動窗口,找到每個窗口的最大值即可。一共會有 N - k + 1 個滑動窗口,每個滑動窗口有 k 個元素,所以時間複雜度爲 O(Nk),表現較差。
方法二:雙端隊列
這裏採用 以雙向鏈表實現的 LinkedList 作爲雙端隊列。
算法
- 遍歷整個數組。
- 把當前元素的索引添加到雙端隊列中,在添加之前首先清理雙端隊列:
- 遍歷當前雙端隊列。
- 移除比當前元素小的所有元素,它們不可能是最大的,保證雙端隊列隊首到隊尾按從大到小的順序排列,這樣保證了隊首永遠是當前窗口最大的。
- 如果隊首的索引超出了窗口,則移除對首。
- 將對首元素添加到輸出數組中。
public int[] maxSlidingWindow(int[] nums, int k) {
if(nums == null || nums.length == 0) return new int[0];
LinkedList<Integer> qmax = new LinkedList<>();
int[] result = new int[nums.length - k + 1];
int index = 0;
for(int i = 0; i < nums.length; i++) {
// 遍歷雙端隊列,將比當前元素小的所有元素移除
while(!qmax.isEmpty() && nums[i] >= nums[qmax.peekLast()]) {
qmax.pollLast();
}
// 將當前元素的索引添加到隊列
qmax.addLast(i);
// 如果隊首的索引超出了窗口,移除
if(qmax.peekFirst() == i - k) {
qmax.pollFirst();
}
// 第一個窗口生成,構建輸出結果
if(i >= k - 1) {
result[index++] = nums[qmax.peekFirst()];
}
}
return result;
}
複雜度
- 時間複雜度:O(N),每個元素被處理兩次,其索引被添加到雙端隊列,和被雙端隊列刪除。
- 空間複雜度:O(N),輸出數組使用了 O(N - k + 1) ,雙端隊列使用了 O(k)。