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. Return the max sliding window.
Follow up: Could you solve it in linear time
?
Example:
Input: nums = [1,3,-1,-3,5,3,6,7], and k = 3
Output: [3,3,5,5,6,7]
Explanation:
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
Constraints:
1 <= nums.length <= 10^5
-10^4 <= nums[i] <= 10^4
1 <= k <= nums.length
題意:給出一個固定大小的區間,區間從數組頭移動到數組尾,返回區間移動過程中的所有區間內部最大值組成的向量。
思路1:暴力做法,超出時間限制。
代碼1: 的時間複雜度。
class Solution {
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
vector<int> ans;
if (nums.empty()) return ans;
for (int i = 0; i <= nums.size() - k; ++i) {
int maxVal = nums[i];
for (int j = i + 1; j < i + k; ++j) {
if (nums[j] > maxVal) maxVal = nums[j];
}
ans.push_back(maxVal);
}
return ans;
}
};
每次都要和區間中的前 k-1
個數比較,時間浪費巨大。如果高效排除不可能成爲答案的數字,就能夠提高效率。
思路2:改進方法一是:使用優先隊列+記錄數字下標的數組,每次將數字進隊,然後取優先隊列的隊首元素。這將時間提升到 ,能夠通過。
代碼2:
class Solution {
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
vector<int> ans;
priority_queue<int, vector<int>, less<int> > q;
map<int, int> mp;
for (int i = 0; i < nums.size(); ++i) {
q.push(nums[i]);
//記錄元素的下標, 如果該元素重複出現, 以最大的下標爲準
mp[nums[i]] = i;
while (mp[q.top()] + k <= i) q.pop();
if (i >= k - 1) ans.push_back(q.top());
}
return ans;
}
};
思路3:使用單調隊列,將普通隊列和優先隊列結合起來,遵循:先進和優先級越高越先出隊的原則。可以達到 的時間要求。
代碼3:
class Solution {
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
vector<int> ans;
int *st, *idx, front = 0, rear = -1;
st = new int[nums.size()], idx = new int[nums.size()];
for (int i = 0; i < nums.size(); ++i) {
while (front <= rear && nums[i] > st[rear]) --rear;
st[++rear] = nums[i];
idx[rear] = i; //記錄位於rear的元素的原數組下標
while (idx[front] + k <= i) ++front; //清除超出範圍的首元素
if (i >= k - 1) ans.push_back(st[front]);
}
return ans;
}
};
另外,這裏可以改成使用 deque
雙端隊列。