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.


Solutions:
(1) use a deque to save the index of all possible max, with current largest max in the window on the peek
To keep the largest on the peek, we pull when the index is out of range and we save each element after removing the prviously added elemnts which are smaller than the current.
Java:
public int[] maxSlidingWindow(int[] a, int k) {
if (a == null || k <= 0) {
return new int[0];
}
int n = a.length;
int[] r = new int[n-k+1];
int ri = 0;
// store index
Deque<Integer> q = new ArrayDeque<>();
for (int i = 0; i < a.length; i++) {
// remove numbers out of range k
while (!q.isEmpty() && q.peek() < i - k + 1) {
q.poll();
}
// remove smaller numbers in k range as they are useless
while (!q.isEmpty() && a[q.peekLast()] < a[i]) {
q.pollLast();
}
// q contains index... r contains content
q.offer(i);
if (i >= k - 1) {
r[ri++] = a[q.peek()];
}
}
return r;
}
// https://leetcode.com/problems/sliding-window-maximum/discuss/65884/Java-O(n)-solution-using-deque-with-explanation
(2) partition array in the blocks , solve by sliding-max(i) = max{right_max(i), left_max(i+w-1)}

Java:
public static int[] slidingWindowMax(final int[] in, final int w) {
final int[] max_left = new int[in.length];
final int[] max_right = new int[in.length];
max_left[0] = in[0];
max_right[in.length - 1] = in[in.length - 1];
for (int i = 1; i < in.length; i++) {
max_left[i] = (i % w == 0) ? in[i] : Math.max(max_left[i - 1], in[i]);
final int j = in.length - i - 1;
max_right[j] = (j % w == 0) ? in[j] : Math.max(max_right[j + 1], in[j]);
}
final int[] sliding_max = new int[in.length - w + 1];
for (int i = 0, j = 0; i + w <= in.length; i++) {
sliding_max[j++] = Math.max(max_right[i], max_left[i + w - 1]);
}
return sliding_max;
}
// https://leetcode.com/problems/sliding-window-maximum/discuss/65881/O(n)-solution-in-Java-with-two-simple-pass-in-the-array


(3) monotonic queue class
save the <value, counts of elements that were deleted before it and the one before it> in the deque
push: push an element after pop_back() all the elements before if they are small [same in solution (1)] and count the number of deleted numbers; O(1) (amortized)
pop: pop an element out of the queue and if the counts if larger than 0, --; O(1) (pop = remove, it can't report this element)
max: report the max element in queue;O(1)
Time: O(n)
C++:
class Monoqueue
{
deque<pair<int, int>> m_deque; //pair.first: the actual value,
//pair.second: how many elements were deleted between it and the one before it.
public:
void push(int val)
{
int count = 0;
while(!m_deque.empty() && m_deque.back().first < val)
{
count += m_deque.back().second + 1;
m_deque.pop_back();
}
m_deque.emplace_back(val, count);
};
int max()
{
return m_deque.front().first;
}
void pop ()
{
if (m_deque.front().second > 0)
{
m_deque.front().second --;
return;
}
m_deque.pop_front();
}
};
struct Solution {
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
vector<int> results;
Monoqueue mq;
k = min(k, (int)nums.size());
int i = 0;
for (;i < k - 1; ++i) //push first k - 1 numbers;
{
mq.push(nums[i]);
}
for (; i < nums.size(); ++i)
{
mq.push(nums[i]); // push a new element to queue;
results.push_back(mq.max()); // report the current max in queue;
mq.pop(); // pop first element in queue;
}
return results;
}
};
// https://leetcode.com/problems/sliding-window-maximum/discuss/65885/This-is-a-typical-monotonic-queue-problem
博客围绕数组滑动窗口最大值问题展开,介绍了三种解决方案。一是用双端队列保存可能的最大值索引;二是将数组分块,通过特定公式求解;三是使用单调队列类,还给出了 Java 和 C++ 代码示例,时间复杂度均为 O(n)。
700

被折叠的 条评论
为什么被折叠?



