239J. Sliding Window Maximum
https://leetcode.com/problems/sliding-window-maximum/
Method Trivial
分析:
暴力法就是O(Nk)。
除此之外最朴素的思想是用heap. 堆的上方始终是最大的值。堆的大小始终保持k个。 当滑动窗户的时候。找到前面的元素删除。但是由于入堆一个 log(k),而随机查找并删除是O(k). 因此用heap其实没啥优势,是O(Nk).
改进: 达到类似的效果,我们可以用一个TreeMap. 其key是值,value是count。值自动排序了很好理解。 TreeMap插入是 log(k),删除是 log(k), 因此是 O(Nlogk).提升了一些。
Method Best: Monotonic Queue.
从上面朴素的思想里想到,注意到其实我们需要的就是一个数据结构,其结构顶是最大值。
而删除的原则和sliding window相同。从sliding window的经验中我们可以想到,
单调递减队列, monotonic decreasing queue 就是这样的数据结构。
class Solution {
public int[] maxSlidingWindow(int[] nums, int k) {
if(nums.length < 1) return nums;
int[] maxs = new int[nums.length - k + 1];
int count = 0;
Deque<Integer> window = new LinkedList<>();
for(int i = 0; i < nums.length; i++){
while(!window.isEmpty() && nums[i] > nums[window.getLast()] ){
window.removeLast();
}
while(!window.isEmpty() && window.getFirst() < i - k + 1){
window.removeFirst();
}
window.addLast(i);
if(i >= k - 1){
maxs[count++] = nums[window.getFirst()];
}
}
return maxs;
}
}
2020年12月的解法: 我觉得可以,似乎比上面的更直观。
class Solution {
public int[] maxSlidingWindow(int[] nums, int k) {
ArrayDeque<Integer> monoQueue = new ArrayDeque<>();
int[] ans = new int[nums.length - k + 1];
int left = 0;
for(int right = 0; right < nums.length; right++){
if( right - left + 1 > k){
if( monoQueue.peekFirst() == nums[left]){
monoQueue.removeFirst();
}
left++;
}
while( !monoQueue.isEmpty() && monoQueue.peekLast() < nums[right]) {
monoQueue.removeLast();
}
monoQueue.addLast(nums[right]);
if( right >= k - 1){
ans[left] = monoQueue.peekFirst();
}
}
return ans;
}
}
来个暴力法也未尝不可:
class Solution {
public int[] maxSlidingWindow(int[] nums, int k) {
if(nums.length < 1){
return new int[]{};
}
int[] maximums = new int[nums.length - k + 1];
for(int i = 0; i < nums.length - k + 1; i++){
int max = nums[i];
for(int j = i; j < i + k; j++){
max = Math.max(max, nums[j]);
}
maximums[i] = max;
}
return maximums;
}
}
2022 写的。
class Solution {
public int[] maxSlidingWindow(int[] nums, int k) {
int[] maxValueInWindow = new int[nums.length - k + 1];
ArrayDeque<Integer> monotonicQueue = new ArrayDeque<>();
for(int i = 0; i < nums.length; i++){
while(monotonicQueue.size() > 0 && monotonicQueue.peekLast() < nums[i]){
monotonicQueue.removeLast();
}
monotonicQueue.offer(nums[i]);
if(i < k - 1) continue;
if(i > k - 1 && monotonicQueue.peekFirst() == nums[i - k]){
monotonicQueue.removeFirst();
}
maxValueInWindow[i - k + 1] = monotonicQueue.peekFirst();
}
return maxValueInWindow;
}
}
2023 写的: 算法和2022一样的 这个题的核心思想不难,但是把代码写bug free有点难度。
class Solution {
public int[] maxSlidingWindow(int[] nums, int k) {
ArrayDeque<Integer> queue = new ArrayDeque<>();
int[] ans = new int[nums.length - k + 1];
for (int i = 0; i < nums.length; i++) {
int num = nums[i];
while (!queue.isEmpty() && num > queue.peekLast()) {
queue.removeLast();
}
queue.addLast(num);
if (i >= k && nums[i - k] == queue.peekFirst()) {
queue.removeFirst();
}
if (i >= k - 1) {
ans[i - k + 1] = queue.peekFirst();
}
}
return ans;
}
}
Last updated
Was this helpful?