diff --git a/src/main/java/com/thealgorithms/stacks/StockSpanProblem.java b/src/main/java/com/thealgorithms/stacks/StockSpanProblem.java
new file mode 100644
index 000000000000..2e9f6863c90a
--- /dev/null
+++ b/src/main/java/com/thealgorithms/stacks/StockSpanProblem.java
@@ -0,0 +1,67 @@
+package com.thealgorithms.stacks;
+
+import java.util.Stack;
+
+/**
+ * Calculates the stock span for each day in a series of stock prices.
+ *
+ *
The span of a price on a given day is the number of consecutive days ending on that day
+ * for which the price was less than or equal to the current day's price.
+ *
+ *
Idea: keep a stack of indices whose prices are strictly greater than the current price.
+ * While processing each day, pop smaller or equal prices because they are part of the current
+ * span. After popping, the nearest greater price left on the stack tells us where the span stops.
+ *
+ *
Time complexity is O(n) because each index is pushed onto the stack once and popped at most
+ * once, so the total number of stack operations grows linearly with the number of prices. This
+ * makes the stack approach efficient because it avoids rechecking earlier days repeatedly, unlike
+ * a naive nested-loop solution that can take O(n^2) time.
+ *
+ *
Example: for prices [100, 80, 60, 70, 60, 75, 85], the spans are
+ * [1, 1, 1, 2, 1, 4, 6].
+ */
+public final class StockSpanProblem {
+ private StockSpanProblem() {
+ }
+
+ /**
+ * Calculates the stock span for each price in the input array.
+ *
+ * @param prices the stock prices
+ * @return the span for each day
+ * @throws IllegalArgumentException if the input array is null
+ */
+ public static int[] calculateSpan(int[] prices) {
+ if (prices == null) {
+ throw new IllegalArgumentException("Input prices cannot be null");
+ }
+
+ int[] spans = new int[prices.length];
+ Stack stack = new Stack<>();
+
+ // Small example:
+ // prices = [100, 80, 60, 70]
+ // spans = [ 1, 1, 1, 2]
+ // When we process 70, we pop 60 because 60 <= 70, so the span becomes 2.
+ //
+ // The stack stores indices of days with prices greater than the current day's price.
+ for (int index = 0; index < prices.length; index++) {
+ // Remove all previous days whose prices are less than or equal to the current price.
+ while (!stack.isEmpty() && prices[stack.peek()] <= prices[index]) {
+ stack.pop();
+ }
+
+ // If the stack is empty, there is no earlier day with a greater price,
+ // so the count will be from day 0 to this day (index + 1).
+ //
+ // Otherwise, the span is the number of days between
+ // the nearest earlier day with a greater price and the current day.
+ spans[index] = stack.isEmpty() ? index + 1 : index - stack.peek();
+
+ // Store the current index as a candidate for future span calculations.
+ stack.push(index);
+ }
+
+ return spans;
+ }
+}
diff --git a/src/test/java/com/thealgorithms/stacks/StockSpanProblemTest.java b/src/test/java/com/thealgorithms/stacks/StockSpanProblemTest.java
new file mode 100644
index 000000000000..2e4ea74691da
--- /dev/null
+++ b/src/test/java/com/thealgorithms/stacks/StockSpanProblemTest.java
@@ -0,0 +1,34 @@
+package com.thealgorithms.stacks;
+
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+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;
+
+class StockSpanProblemTest {
+
+ @ParameterizedTest
+ @MethodSource("validTestCases")
+ void testCalculateSpan(int[] prices, int[] expectedSpans) {
+ assertArrayEquals(expectedSpans, StockSpanProblem.calculateSpan(prices));
+ }
+
+ private static Stream validTestCases() {
+ return Stream.of(Arguments.of(new int[] {10, 4, 5, 90, 120, 80}, new int[] {1, 1, 2, 4, 5, 1}), Arguments.of(new int[] {100, 50, 60, 70, 80, 90}, new int[] {1, 1, 2, 3, 4, 5}), Arguments.of(new int[] {5, 4, 3, 2, 1}, new int[] {1, 1, 1, 1, 1}),
+ Arguments.of(new int[] {1, 2, 3, 4, 5}, new int[] {1, 2, 3, 4, 5}), Arguments.of(new int[] {10, 20, 30, 40, 50}, new int[] {1, 2, 3, 4, 5}), Arguments.of(new int[] {100, 80, 60, 70, 60, 75, 85}, new int[] {1, 1, 1, 2, 1, 4, 6}),
+ Arguments.of(new int[] {7, 7, 7, 7}, new int[] {1, 2, 3, 4}), Arguments.of(new int[] {}, new int[] {}), Arguments.of(new int[] {42}, new int[] {1}));
+ }
+
+ @ParameterizedTest
+ @MethodSource("invalidTestCases")
+ void testCalculateSpanInvalidInput(int[] prices) {
+ assertThrows(IllegalArgumentException.class, () -> StockSpanProblem.calculateSpan(prices));
+ }
+
+ private static Stream invalidTestCases() {
+ return Stream.of(Arguments.of((int[]) null));
+ }
+}