Add SlidingWindowMaximum algorithm (#5839)

This commit is contained in:
Hardik Pawar
2024-10-26 17:42:55 +05:30
committed by GitHub
parent f20f8d1836
commit 04e421b837
3 changed files with 115 additions and 0 deletions

View File

@ -207,6 +207,7 @@
* [PriorityQueues](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/queues/PriorityQueues.java) * [PriorityQueues](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/queues/PriorityQueues.java)
* [Queue](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/queues/Queue.java) * [Queue](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/queues/Queue.java)
* [QueueByTwoStacks](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/queues/QueueByTwoStacks.java) * [QueueByTwoStacks](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/queues/QueueByTwoStacks.java)
* [SlidingWindowMaximum](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/queues/SlidingWindowMaximum.java)
* [TokenBucket](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/queues/TokenBucket.java) * [TokenBucket](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/queues/TokenBucket.java)
* stacks * stacks
* [NodeStack](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/stacks/NodeStack.java) * [NodeStack](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/stacks/NodeStack.java)
@ -882,6 +883,7 @@
* [PriorityQueuesTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/queues/PriorityQueuesTest.java) * [PriorityQueuesTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/queues/PriorityQueuesTest.java)
* [QueueByTwoStacksTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/queues/QueueByTwoStacksTest.java) * [QueueByTwoStacksTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/queues/QueueByTwoStacksTest.java)
* [QueueTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/queues/QueueTest.java) * [QueueTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/queues/QueueTest.java)
* [SlidingWindowMaximumTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/queues/SlidingWindowMaximumTest.java)
* [TokenBucketTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/queues/TokenBucketTest.java) * [TokenBucketTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/queues/TokenBucketTest.java)
* stacks * stacks
* [NodeStackTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/stacks/NodeStackTest.java) * [NodeStackTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/stacks/NodeStackTest.java)

View File

@ -0,0 +1,63 @@
package com.thealgorithms.datastructures.queues;
import java.util.Deque;
import java.util.LinkedList;
/**
* The {@code SlidingWindowMaximum} class provides a method to efficiently compute
* the maximum element within every sliding window of size {@code k} in a given array.
*
* <p>The algorithm uses a deque to maintain the indices of useful elements within
* the current sliding window. The time complexity of this approach is O(n) since
* each element is processed at most twice.
*
* @author Hardvan
*/
public final class SlidingWindowMaximum {
private SlidingWindowMaximum() {
}
/**
* Returns an array of the maximum values for each sliding window of size {@code k}.
* <p>If {@code nums} has fewer elements than {@code k}, the result will be an empty array.
* <p>Example:
* <pre>
* Input: nums = [1, 3, -1, -3, 5, 3, 6, 7], k = 3
* Output: [3, 3, 5, 5, 6, 7]
* </pre>
*
* @param nums the input array of integers
* @param k the size of the sliding window
* @return an array containing the maximum element for each sliding window
*/
public static int[] maxSlidingWindow(int[] nums, int k) {
int n = nums.length;
if (n < k || k == 0) {
return new int[0];
}
int[] result = new int[n - k + 1];
Deque<Integer> deque = new LinkedList<>();
for (int i = 0; i < n; i++) {
// Remove elements from the front of the deque if they are out of the current window
if (!deque.isEmpty() && deque.peekFirst() < i - k + 1) {
deque.pollFirst();
}
// Remove elements from the back if they are smaller than the current element
while (!deque.isEmpty() && nums[deque.peekLast()] < nums[i]) {
deque.pollLast();
}
// Add the current element's index to the deque
deque.offerLast(i);
// Store the maximum element for the current window (starting from the k-1th element)
if (i >= k - 1) {
result[i - k + 1] = nums[deque.peekFirst()];
}
}
return result;
}
}

View File

@ -0,0 +1,50 @@
package com.thealgorithms.datastructures.queues;
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import java.util.stream.Stream;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
public class SlidingWindowMaximumTest {
@ParameterizedTest
@MethodSource("provideTestCases")
public void testMaxSlidingWindow(int[] nums, int k, int[] expected) {
assertArrayEquals(expected, SlidingWindowMaximum.maxSlidingWindow(nums, k));
}
private static Stream<Arguments> provideTestCases() {
return Stream.of(
// Test case 1: Example from the problem statement
Arguments.of(new int[] {1, 3, -1, -3, 5, 3, 6, 7}, 3, new int[] {3, 3, 5, 5, 6, 7}),
// Test case 2: All elements are the same
Arguments.of(new int[] {4, 4, 4, 4, 4}, 2, new int[] {4, 4, 4, 4}),
// Test case 3: Window size equals the array length
Arguments.of(new int[] {2, 1, 5, 3, 6}, 5, new int[] {6}),
// Test case 4: Single element array with window size 1
Arguments.of(new int[] {7}, 1, new int[] {7}),
// Test case 5: Window size larger than the array length
Arguments.of(new int[] {1, 2, 3}, 4, new int[] {}),
// Test case 6: Decreasing sequence
Arguments.of(new int[] {9, 8, 7, 6, 5, 4}, 3, new int[] {9, 8, 7, 6}),
// Test case 7: Increasing sequence
Arguments.of(new int[] {1, 2, 3, 4, 5}, 2, new int[] {2, 3, 4, 5}),
// Test case 8: k is zero
Arguments.of(new int[] {1, 3, -1, -3, 5, 3, 6, 7}, 0, new int[] {}),
// Test case 9: Array with negative numbers
Arguments.of(new int[] {-4, -2, -5, -1, -3}, 3, new int[] {-2, -1, -1}),
// Test case 10: Empty array
Arguments.of(new int[] {}, 3, new int[] {}));
}
}