解题思路
最开始的想法是维护一个List,每次滑动移除nums[left]加入nums[right],并对list进行重新排序,取出最大的值即可,但是最后超时
学习之后决定使用双端队列
总体的基本思想就是维护住一个依次递减的双端队列
总结为:以下几点
1.队首元素是当前的最大元素,如果新元素小于队尾元素,那么就直接加入队尾,如果大于队尾元素,则队尾元素出队
2.判断当前窗口的第一个元素是否和队头元素相等,如果相等队头元素出队
3.继续然后按照规则进行入队,维护单调递减队列。
代码
第一个版本因为时间复杂度太高需要进行重排序,所以不能使用了49 / 60 个通过测试用例
第二个版本是使用双端队列LinkedList完美解决
public int[] maxSlidingWindow(int[] nums, int k) {
int n = nums.length,right = k,left=0;
List<Integer> temp = new ArrayList<>();
if (n<k){
return new int[]{};
}
int[] ans = new int[n-k+1];
for (int i=0;i<k;i++){
temp.add(nums[i]);
}
while (right<n){
Collections.sort(temp);
ans[left]=temp.get(k-1);
temp.remove(temp.indexOf(nums[left]));
temp.add(nums[right]);
left++;
right++;
}
Collections.sort(temp);
ans[left]=temp.get(k-1);
return ans;
}
public int[] maxSlidingWindow2(int[] nums, int k) {
int n = nums.length,right = k,left=0;
LinkedList<Integer> temp = new LinkedList<>();//使用双端队列
if (k==1){
return nums;
}
int[] ans = new int[n-k+1];
temp.offer(nums[0]);
for (int i=1;i<k;i++){
while (!temp.isEmpty() && nums[i]>temp.getLast()){
temp.removeLast();
}
temp.offer(nums[i]);
}
while (right<n){
ans[left]=temp.getFirst();
if (temp.getFirst()==nums[left]){
temp.removeFirst();
}
while (!temp.isEmpty() && nums[right]>temp.getLast()){
temp.removeLast();
}
temp.offer(nums[right]);
right++;
left++;
}
ans[left]=temp.getFirst();
return ans;
}