Given an array nums, there is a sliding window of size k which is moving from the very left of the array to the very right. You can only see the k numbers in the window. Each time the sliding window moves right by one position.
For example,
Given nums = [1,3,-1,-3,5,3,6,7], and k = 3.
Window position Max
--------------- -----
[1 3 -1] -3 5 3 6 7 3
1 [3 -1 -3] 5 3 6 7 3
1 3 [-1 -3 5] 3 6 7 5
1 3 -1 [-3 5 3] 6 7 5
1 3 -1 -3 [5 3 6] 7 6
1 3 -1 -3 5 [3 6 7] 7
Therefore, return the max sliding window as [3,3,5,5,6,7].
思路1:general idea: 我们需要maintain一个固定长度的window,所以每次遇到新元素需要放进来和po出去,同时,我们还需要去看window中的最大值,因此,我们想到用priorityqueue或者treemap,这两者都可以实现看极值,删除某个极值,加入某个值的操作,但是priorityqueue的操作平均复杂度是O(logn),因此我们用priorityqueue。另外,我们需要注意的一点是,treemap里不可以放index和值,因为treemap是按照key排序的,所以需要放值和次数,删除的时候我们可以根据下标来索引删除。
public int[] maxSlidingWindow(int[] nums, int k) {
//special case
if (nums == null || nums.length < k || k == 0) return new int[0];
//base case
int[] res = new int[nums.length - k + 1];
TreeMap<Integer,Integer> map = new TreeMap<>((o1, o2) -> (o1 - o2));
for (int i = 0; i < k - 1; i++) {
map.put(nums[i], map.getOrDefault(nums[i], 0) + 1);
}
//general case
for (int i = k - 1; i < nums.length; i++) {
map.put(nums[i], map.getOrDefault(nums[i], 0) + 1);
//注意,这里我们不能用map.size()>k,因为会有重复元素。
if (i >= k) {
if (map.get(nums[i - k]) > 1) {
map.put(nums[i - k], map.get(nums[i - k]) - 1);
} else {
map.remove(nums[i - k]);
}
}
res[i - k + 1] = map.lastKey();
}
return res;
}
思路2:用Deque来做,保证deque里的元素是递减的,同时,当下标达到需要po出去的地方,就po出去。
public int[] maxSlidingWindow(int[] nums, int k) {
//special case
if (nums == null || nums.length < k || k == 0) return new int[0];
//general case
int[] res = new int[nums.length - k + 1];
Deque<Integer> deque = new LinkedList<>();
for (int i = 0; i < nums.length; i++) {
//step 1: 尾部加元素,保证左边元素都比尾部大
while (!deque.isEmpty() && nums[deque.getLast()] < nums[i]) {
deque.removeLast();
}
deque.addLast(i);
//step 2: 头部剪元素
if (deque.getFirst() == i - k) {
deque.removeFirst();
}
//输出结果
if (i >= k - 1) {
res[i - k + 1] = nums[deque.getFirst()];
}
}
return res;
}