Skip to content

Added Maximum Sliding Window algorithm using deque for efficient O(n) solution. #5848

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Oct 26, 2024
Merged
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package com.thealgorithms.others;

import java.util.ArrayDeque;
import java.util.Deque;

/**
* Maximum Sliding Window Algorithm
*
* This algorithm finds the maximum element in each sliding window of size k
* in a given array of integers. It uses a deque (double-ended queue) to
* efficiently keep track of potential maximum values in the current window.
*
* Time Complexity: O(n), where n is the number of elements in the input array
* Space Complexity: O(k), where k is the size of the sliding window
*/

public class MaximumSlidingWindow {

/**
* Finds the maximum values in each sliding window of size k.
*
* @param nums The input array of integers
* @param windowSize The size of the sliding window
* @return An array of integers representing the maximums in each window
*/
public int[] maxSlidingWindow(int[] nums, int windowSize) {
if (nums == null || nums.length == 0 || windowSize <= 0 || windowSize > nums.length) {
return new int[0]; // Handle edge cases
}

int[] result = new int[nums.length - windowSize + 1];
Deque<Integer> deque = new ArrayDeque<>();

for (int currentIndex = 0; currentIndex < nums.length; currentIndex++) {

// Remove the first element if it's outside the current window
if (!deque.isEmpty() && deque.peekFirst() == currentIndex - windowSize) {
deque.pollFirst();
}

// Remove all elements smaller than the current element from the end
while (!deque.isEmpty() && nums[deque.peekLast()] < nums[currentIndex]) {
deque.pollLast();
}

// Add the current element's index to the deque
deque.offerLast(currentIndex);

// If we have processed at least k elements, add to result
if (currentIndex >= windowSize - 1) {
result[currentIndex - windowSize + 1] = nums[deque.peekFirst()];
}
}
return result;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package com.thealgorithms.others;

import static org.junit.jupiter.api.Assertions.assertArrayEquals;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

class MaximumSlidingWindowTest {

MaximumSlidingWindow msw;
int[] nums;
int k;

@BeforeEach
void setUp() {
msw = new MaximumSlidingWindow(); // Initialize the MaximumSlidingWindow object
}

// Test for a simple sliding window case
@Test
void testMaxSlidingWindowSimpleCase() {
nums = new int[] {1, 3, -1, -3, 5, 3, 6, 7};
k = 3;
int[] expected = {3, 3, 5, 5, 6, 7};
assertArrayEquals(expected, msw.maxSlidingWindow(nums, k));
}

// Test when window size is 1 (output should be the array itself)
@Test
void testMaxSlidingWindowWindowSizeOne() {
nums = new int[] {4, 2, 12, 11, -5};
k = 1;
int[] expected = {4, 2, 12, 11, -5};
assertArrayEquals(expected, msw.maxSlidingWindow(nums, k));
}

// Test when the window size is equal to the array length (output should be a single max element)
@Test
void testMaxSlidingWindowWindowSizeEqualsArrayLength() {
nums = new int[] {4, 2, 12, 11, -5};
k = nums.length;
int[] expected = {12}; // Maximum of the entire array
assertArrayEquals(expected, msw.maxSlidingWindow(nums, k));
}

// Test when the input array is empty
@Test
void testMaxSlidingWindowEmptyArray() {
nums = new int[] {};
k = 3;
int[] expected = {};
assertArrayEquals(expected, msw.maxSlidingWindow(nums, k));
}

// Test when the window size is larger than the array (should return empty)
@Test
void testMaxSlidingWindowWindowSizeLargerThanArray() {
nums = new int[] {1, 2, 3};
k = 5;
int[] expected = {}; // Window size is too large, so no result
assertArrayEquals(expected, msw.maxSlidingWindow(nums, k));
}
}