diff --git a/src/main/java/com/thealgorithms/datastructures/stacks/NearestElement.java b/src/main/java/com/thealgorithms/datastructures/stacks/NearestElement.java new file mode 100644 index 000000000000..8fe8c2821ccb --- /dev/null +++ b/src/main/java/com/thealgorithms/datastructures/stacks/NearestElement.java @@ -0,0 +1,84 @@ +package com.thealgorithms.datastructures.stacks; + +import java.util.Stack; + +/** + * The {@code NearestElement} class provides static utility methods to find the + * nearest greater or smaller elements to the left or right of each element in + * an integer array using stack-based algorithms. + * + *

+ * Each method runs in O(n) time complexity by maintaining a monotonic stack: + *

+ */ +public final class NearestElement { + + private NearestElement() { + throw new UnsupportedOperationException("Utility class"); + } + + public static int[] nearestGreaterToRight(int[] arr) { + int n = arr.length; + int[] result = new int[n]; + Stack stack = new Stack<>(); + for (int i = n - 1; i >= 0; i--) { + while (!stack.isEmpty() && stack.peek() <= arr[i]) { + stack.pop(); + } + result[i] = stack.isEmpty() ? -1 : stack.peek(); + stack.push(arr[i]); + } + return result; + } + + public static int[] nearestGreaterToLeft(int[] arr) { + int n = arr.length; + int[] result = new int[n]; + Stack stack = new Stack<>(); + for (int i = 0; i < n; i++) { + while (!stack.isEmpty() && stack.peek() <= arr[i]) { + stack.pop(); + } + result[i] = stack.isEmpty() ? -1 : stack.peek(); + stack.push(arr[i]); + } + return result; + } + + public static int[] nearestSmallerToRight(int[] arr) { + int n = arr.length; + int[] result = new int[n]; + Stack stack = new Stack<>(); + for (int i = n - 1; i >= 0; i--) { + while (!stack.isEmpty() && stack.peek() >= arr[i]) { + stack.pop(); + } + result[i] = stack.isEmpty() ? -1 : stack.peek(); + stack.push(arr[i]); + } + return result; + } + + public static int[] nearestSmallerToLeft(int[] arr) { + int n = arr.length; + int[] result = new int[n]; + Stack stack = new Stack<>(); + for (int i = 0; i < n; i++) { + while (!stack.isEmpty() && stack.peek() >= arr[i]) { + stack.pop(); + } + result[i] = stack.isEmpty() ? -1 : stack.peek(); + stack.push(arr[i]); + } + return result; + } +} diff --git a/src/test/java/com/thealgorithms/stacks/NearestElementTest.java b/src/test/java/com/thealgorithms/stacks/NearestElementTest.java new file mode 100644 index 000000000000..e6b30e826883 --- /dev/null +++ b/src/test/java/com/thealgorithms/stacks/NearestElementTest.java @@ -0,0 +1,59 @@ +package com.thealgorithms.stacks; + +import java.lang.reflect.Constructor; +import java.util.Arrays; + +import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import org.junit.jupiter.api.Test; + +import com.thealgorithms.datastructures.stacks.NearestElement; + + +class NearestElementTest { + + @Test + void testNearestGreaterToRight() { + int[] arr = {4, 5, 2, 10, 8}; + int[] result = NearestElement.nearestGreaterToRight(arr); + System.out.println("nearestGreaterToRight: " + Arrays.toString(result)); + int[] expected = {5, 10, 10, -1, -1}; + assertArrayEquals(expected, result); + } + + @Test + void testNearestGreaterToLeft() { + int[] arr = {4, 5, 2, 10, 8}; + int[] result = NearestElement.nearestGreaterToLeft(arr); + System.out.println("nearestGreaterToLeft: " + Arrays.toString(result)); + int[] expected = {-1, -1, 5, -1, 10}; + assertArrayEquals(expected, result); + } + + @Test + void testNearestSmallerToRight() { + int[] arr = {4, 5, 2, 10, 8}; + int[] result = NearestElement.nearestSmallerToRight(arr); + System.out.println("nearestSmallerToRight: " + Arrays.toString(result)); + int[] expected = {2, 2, -1, 8, -1}; + assertArrayEquals(expected, result); + } + + @Test + void testNearestSmallerToLeft() { + int[] arr = {4, 5, 2, 10, 8}; + int[] result = NearestElement.nearestSmallerToLeft(arr); + System.out.println("nearestSmallerToLeft: " + Arrays.toString(result)); + int[] expected = {-1, 4, -1, 2, 2}; + assertArrayEquals(expected, result); + } + + @Test + void testPrivateConstructor() throws Exception { + Constructor constructor = NearestElement.class.getDeclaredConstructor(); + constructor.setAccessible(true); + try { + constructor.newInstance(); + } catch (Exception ignored) { + } + } +}