剑指 Offer 59 - I. 滑动窗口的最大值(双端队列)
题目描述:
239 题:滑动窗口法
leetcode. [239]滑动窗口最大值(B-F(暴力实现),PQ(优先队列),Deque(双端队列),DP(动态规划))
解题思路:
方法一:
暴力法
代码:
class Solution {
public int[] maxSlidingWindow(int[] nums, int k) {
int n = nums.length;
if (n * k == 0) return new int[0];
int [] output = new int[n - k + 1];
for (int i = 0; i < n - k + 1; i++) {
int max = Integer.MIN_VALUE;
for(int j = i; j < i + k; j++)
max = Math.max(max, nums[j]);
output[i] = max;
}
return output;
}
}
方法二:双端队列
public int[] maxSlidingWindow(int[] nums, int k) {
if (nums.length == 0 || k == 0) return new int[0];
Deque<Integer> deque = new LinkedList<>();
int[] res = new int[nums.length - k + 1];
for (int j = 0,i = 1 - k; j < nums.length;i++, j++) {
if (i > 0 && deque.peekFirst() == nums[i - 1])
deque.removeFirst(); //删除deque中对应的nums[i-1]
while (!deque.isEmpty() && deque.peekLast() < nums[j])
deque.removeLast(); // 保持deque递减
deque.addLast(nums[j]);
if (i >= 0){
res[i] = deque.peekFirst(); //记录窗口最大值
}
}
return res;
}
class Solution {
ArrayDeque<Integer> deq = new ArrayDeque<Integer>();
int [] nums;
public void clean_deque(int i, int k) {
// remove indexes of elements not from sliding window
if (!deq.isEmpty() && deq.getFirst() == i - k)
deq.removeFirst();
// remove from deq indexes of all elements
// which are smaller than current element nums[i]
while (!deq.isEmpty() && nums[i] > nums[deq.getLast()]) deq.removeLast();
}
public int[] maxSlidingWindow(int[] nums, int k) {
int n = nums.length;
if (n * k == 0) return new int[0];
if (k == 1) return nums;
// init deque and output
this.nums = nums;
int max_idx = 0;
for (int i = 0; i < k; i++) {
clean_deque(i, k);
deq.addLast(i);
// compute max in nums[:k]
if (nums[i] > nums[max_idx]) max_idx = i;
}
int [] output = new int[n - k + 1];
output[0] = nums[max_idx];
// build output
for (int i = k; i < n; i++) {
clean_deque(i, k);
deq.addLast(i);
output[i - k + 1] = nums[deq.getFirst()];
}
return output;
}
}