思路:结果集的大小应该为 res = new int[n - k + 1],边界条件有 n == 0, k == 1
class Solution {
public int[] maxSlidingWindow(int[] nums, int k) {
if(nums.length==0) return new int[0];
if(k == 1) return nums;
int n = nums.length;
int[] res = new int[n - k + 1];
// 循环 n - k + 1 次
for(int i = 0; i < n - k + 1; i++){
int temp = Integer.MIN_VALUE;
for(int j = i; j < k + i; j++){
// 循环 k 次
temp = Math.max(temp, nums[j]);
}
res[i] = temp;
}
return res;
}
}
class Solution {
public int[] maxSlidingWindow(int[] nums, int k) {
if(nums.length==0) return new int[0];
if(k == 1) return nums;
int n = nums.length;
int i = 0, j = i + k - 1;
int[] res = new int[n - k + 1];
int index = 0;
while(j < n){
int temp = Integer.MIN_VALUE;
for(int x = i; x <= j; x++){
temp = Math.max(temp, nums[x]);
}
res[index++] = temp;
i++;
j++;
}
return res;
}
}
以上的时间复杂度都是O(n−k+1) * O(k)≈O(nk)
主要是窗口内需要排序 k
次。
思路2:使用单调队列 deque 记录窗口中的最大值。
class Solution {
public static 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];
int arr_index = 0;
// 还未形成窗口
for(int i = 0; i < k; i++){
// 如果单调队列的队尾小于要入队的元素nums[i]
while (!deque.isEmpty() && deque.peekLast() < nums[i]){
deque.removeLast();
}
// nums[i] 入队
deque.offerLast(nums[i]);
}
res[arr_index++] = deque.peekFirst();
// 形成窗口
for (int i = k; i < nums.length; i++) {
// 窗口滑动时,nums[i - k] 移出了窗口,如果移出了窗口的值nums[i - k]刚好是最大值,需将 deque 内的对应元素一起删除
if (nums[i - k] == deque.peekFirst()){
deque.removeFirst();
}
while (!deque.isEmpty() && deque.peekLast() < nums[i]){
deque.removeLast();
}
deque.offerLast(nums[i]);
res[arr_index++] = deque.peekFirst();
}
return res;
}
public static void main(String[] args) {
int[] arr = {1,3,-1,-3,5,3,6,7};
int[] res = maxSlidingWindow(arr, 3);
System.out.println(Arrays.toString(res));
}
}