刷题顺序按照代码随想录建议
题目描述
英文版描述
You are given an array of integers 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.
Return the max sliding window.
Example 1:
Example 2:
Input: nums = [1], k = 1 Output: [1]
Constraints
1 <= nums.length <= 10^5
-10^4 <= nums[i] <= 10^4
1 <= k <= nums.length
英文版地址
中文版描述
给你一个整数数组 nums
,有一个大小为 k
**的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k
个数字。滑动窗口每次只向右移动一位。
返回 滑动窗口中的最大值 。
示例 1:
示例 2:
输入: nums = [1], k = 1 输出: [1]
提示:
1 <= nums.length <= 10^5
-10^4 <= nums[i] <= 10^4
1 <= k <= nums.length
中文版地址
解题方法
俺这版
比较直接的思路,呜呜呜呜~超时了
java
class Solution {
public int[] maxSlidingWindow(int[] nums, int k) {
if (nums == null) {
return null;
}
Queue<Integer> result = new LinkedList<>();
int len = nums.length;
for (int i = 0; i < len - k + 1; i++) {
int subMax = nums[i];
for (int j = i; j < i + k; j++) {
subMax = Math.max(subMax, nums[j]);
}
result.add(subMax);
}
return result.stream().mapToInt(Integer::intValue).toArray();
}
}
复杂度分析
- 时间复杂度:O(nk),其中 n 是数组 nums 的长度,k是窗口长度,嵌套了两层for循环。
- 空间复杂度:O(1),只有subMax一个额外变量
官方版
方法一:双端队列
java
class Solution {
public int[] maxSlidingWindow(int[] nums, int k) {
if (nums == null) {
return null;
}
ArrayDeque<Integer> queueIndex = new ArrayDeque<>();
Queue<Integer> result = new LinkedList<>();
int len = nums.length;
for (int i = 0; i < len; i++) {
while (!queueIndex.isEmpty() && queueIndex.peekFirst() < i - k + 1) {
queueIndex.pollFirst();
}
while (!queueIndex.isEmpty() && nums[i] > nums[queueIndex.peekLast()]) {
queueIndex.pollLast();
}
queueIndex.add(i);
if (i >= k - 1) {
result.add(nums[queueIndex.peekFirst()]);
}
}
return result.stream().mapToInt(Integer::intValue).toArray();
}
}
复杂度分析
-
时间复杂度:O(n),其中 n 是数组 nums 的长度。每一个下标恰好被放入队列一次,并且最多被弹出队列一次,因此时间复杂度为 O(n)。
-
空间复杂度:O(k),对列里不会存储超过k个元素。
方法二:优先队列
java
class Solution {
public int[] maxSlidingWindow(int[] nums, int k) {
int n = nums.length;
PriorityQueue<int[]> pq = new PriorityQueue<int[]>(new Comparator<int[]>() {
public int compare(int[] pair1, int[] pair2) {
return pair1[0] != pair2[0] ? pair2[0] - pair1[0] : pair2[1] - pair1[1];
}
});
for (int i = 0; i < k; ++i) {
pq.offer(new int[]{nums[i], i});
}
int[] ans = new int[n - k + 1];
ans[0] = pq.peek()[0];
for (int i = k; i < n; ++i) {
pq.offer(new int[]{nums[i], i});
while (pq.peek()[1] <= i - k) {
pq.poll();
}
ans[i - k + 1] = pq.peek()[0];
}
return ans;
}
}
复杂度分析
- 时间复杂度:O(nlogn),其中 n 是数组 nums 的长度。在最坏情况下,数组 nums 中的元素单调递增,那么最终优先队列中包含了所有元素,没有元素被移除。由于将一个元素放入优先队列的时间复杂度为 O(logn),因此总时间复杂度为 O(nlogn)
- 空间复杂度:O(n),即为优先队列需要使用的空间。这里所有的空间复杂度分析都不考虑返回的答案需要的 O(n) 空间,只计算额外的空间使用