From 12022a155b4bb16c803b1d449bd69e5d706048ed Mon Sep 17 00:00:00 2001 From: alxkm Date: Tue, 8 Jul 2025 23:33:49 +0200 Subject: [PATCH 1/3] refactor: clean up LargestRectangle and convert tests to parameterized format --- .../stacks/LargestRectangle.java | 50 +++++++----- .../stacks/LargestRectangleTest.java | 78 ++++--------------- 2 files changed, 46 insertions(+), 82 deletions(-) diff --git a/src/main/java/com/thealgorithms/stacks/LargestRectangle.java b/src/main/java/com/thealgorithms/stacks/LargestRectangle.java index 006e03632e63..673fc8e00d32 100644 --- a/src/main/java/com/thealgorithms/stacks/LargestRectangle.java +++ b/src/main/java/com/thealgorithms/stacks/LargestRectangle.java @@ -3,36 +3,50 @@ import java.util.Stack; /** + * Utility class to calculate the largest rectangle area in a histogram. + * Each bar's width is assumed to be 1 unit. * - * @author mohd rameez github.com/rameez471 + *

This implementation uses a monotonic stack to efficiently calculate + * the area of the largest rectangle that can be formed from the histogram bars.

+ * + *

Example usage: + *

{@code
+ *     int[] heights = {2, 1, 5, 6, 2, 3};
+ *     String area = LargestRectangle.largestRectangleHistogram(heights);
+ *     // area is "10"
+ * }
*/ - public final class LargestRectangle { + private LargestRectangle() { } + /** + * Calculates the largest rectangle area in the given histogram. + * + * @param heights an array of non-negative integers representing bar heights + * @return the largest rectangle area as a {@link String} + */ public static String largestRectangleHistogram(int[] heights) { - int n = heights.length; int maxArea = 0; - Stack st = new Stack<>(); - for (int i = 0; i < n; i++) { + Stack stack = new Stack<>(); + + for (int i = 0; i < heights.length; i++) { int start = i; - while (!st.isEmpty() && st.peek()[1] > heights[i]) { - int[] tmp = st.pop(); - maxArea = Math.max(maxArea, tmp[1] * (i - tmp[0])); - start = tmp[0]; + while (!stack.isEmpty() && stack.peek()[1] > heights[i]) { + int[] popped = stack.pop(); + maxArea = Math.max(maxArea, popped[1] * (i - popped[0])); + start = popped[0]; } - st.push(new int[] {start, heights[i]}); + stack.push(new int[]{start, heights[i]}); } - while (!st.isEmpty()) { - int[] tmp = st.pop(); - maxArea = Math.max(maxArea, tmp[1] * (n - tmp[0])); + + int totalLength = heights.length; + while (!stack.isEmpty()) { + int[] remaining = stack.pop(); + maxArea = Math.max(maxArea, remaining[1] * (totalLength - remaining[0])); } - return Integer.toString(maxArea); - } - public static void main(String[] args) { - assert largestRectangleHistogram(new int[] {2, 1, 5, 6, 2, 3}).equals("10"); - assert largestRectangleHistogram(new int[] {2, 4}).equals("4"); + return Integer.toString(maxArea); } } diff --git a/src/test/java/com/thealgorithms/stacks/LargestRectangleTest.java b/src/test/java/com/thealgorithms/stacks/LargestRectangleTest.java index a54372adda0e..da61e54c3e60 100644 --- a/src/test/java/com/thealgorithms/stacks/LargestRectangleTest.java +++ b/src/test/java/com/thealgorithms/stacks/LargestRectangleTest.java @@ -2,76 +2,26 @@ import static org.junit.jupiter.api.Assertions.assertEquals; -import org.junit.jupiter.api.Test; +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 LargestRectangleTest { - @Test - void testLargestRectangleHistogramWithTypicalCases() { - // Typical case with mixed heights - int[] heights = {2, 1, 5, 6, 2, 3}; - String expected = "10"; - String result = LargestRectangle.largestRectangleHistogram(heights); - assertEquals(expected, result); - - // Another typical case with increasing heights - heights = new int[] {2, 4}; - expected = "4"; - result = LargestRectangle.largestRectangleHistogram(heights); - assertEquals(expected, result); - - // Case with multiple bars of the same height - heights = new int[] {4, 4, 4, 4}; - expected = "16"; - result = LargestRectangle.largestRectangleHistogram(heights); - assertEquals(expected, result); + @ParameterizedTest(name = "Histogram: {0} → Expected area: {1}") + @MethodSource("histogramProvider") + void testLargestRectangleHistogram(int[] heights, String expected) { + assertEquals(expected, LargestRectangle.largestRectangleHistogram(heights)); } - @Test - void testLargestRectangleHistogramWithEdgeCases() { - // Edge case with an empty array - int[] heights = {}; - String expected = "0"; - String result = LargestRectangle.largestRectangleHistogram(heights); - assertEquals(expected, result); - - // Edge case with a single bar - heights = new int[] {5}; - expected = "5"; - result = LargestRectangle.largestRectangleHistogram(heights); - assertEquals(expected, result); - - // Edge case with all bars of height 0 - heights = new int[] {0, 0, 0}; - expected = "0"; - result = LargestRectangle.largestRectangleHistogram(heights); - assertEquals(expected, result); + static Stream histogramProvider() { + return Stream.of(Arguments.of(new int[]{2, 1, 5, 6, 2, 3}, "10"), Arguments.of(new int[]{2, 4}, "4"), Arguments.of(new int[]{4, 4, 4, 4}, "16"), Arguments.of(new int[]{}, "0"), Arguments.of(new int[]{5}, "5"), Arguments.of(new int[]{0, 0, 0}, "0"), Arguments.of(new int[]{6, 2, 5, 4, 5, 1, 6}, "12"), Arguments.of(new int[]{2, 1, 5, 6, 2, 3, 1}, "10"), Arguments.of(createLargeArray(10000, 1), "10000")); } - @Test - void testLargestRectangleHistogramWithLargeInput() { - // Large input case - int[] heights = new int[10000]; - for (int i = 0; i < heights.length; i++) { - heights[i] = 1; - } - String expected = "10000"; - String result = LargestRectangle.largestRectangleHistogram(heights); - assertEquals(expected, result); - } - - @Test - void testLargestRectangleHistogramWithComplexCases() { - // Complex case with a mix of heights - int[] heights = {6, 2, 5, 4, 5, 1, 6}; - String expected = "12"; - String result = LargestRectangle.largestRectangleHistogram(heights); - assertEquals(expected, result); - - // Case with a peak in the middle - heights = new int[] {2, 1, 5, 6, 2, 3, 1}; - expected = "10"; - result = LargestRectangle.largestRectangleHistogram(heights); - assertEquals(expected, result); + private static int[] createLargeArray(int size, int value) { + int[] arr = new int[size]; + java.util.Arrays.fill(arr, value); + return arr; } } From 175714700b12a4db2d602a6286d8a4af2e4bac78 Mon Sep 17 00:00:00 2001 From: alxkm Date: Tue, 8 Jul 2025 23:37:29 +0200 Subject: [PATCH 2/3] refactor: fix clang formatting issue --- src/main/java/com/thealgorithms/stacks/LargestRectangle.java | 2 +- .../java/com/thealgorithms/stacks/LargestRectangleTest.java | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/thealgorithms/stacks/LargestRectangle.java b/src/main/java/com/thealgorithms/stacks/LargestRectangle.java index 673fc8e00d32..eb222c8c488e 100644 --- a/src/main/java/com/thealgorithms/stacks/LargestRectangle.java +++ b/src/main/java/com/thealgorithms/stacks/LargestRectangle.java @@ -38,7 +38,7 @@ public static String largestRectangleHistogram(int[] heights) { maxArea = Math.max(maxArea, popped[1] * (i - popped[0])); start = popped[0]; } - stack.push(new int[]{start, heights[i]}); + stack.push(new int[] {start, heights[i]}); } int totalLength = heights.length; diff --git a/src/test/java/com/thealgorithms/stacks/LargestRectangleTest.java b/src/test/java/com/thealgorithms/stacks/LargestRectangleTest.java index da61e54c3e60..fa4f17bda669 100644 --- a/src/test/java/com/thealgorithms/stacks/LargestRectangleTest.java +++ b/src/test/java/com/thealgorithms/stacks/LargestRectangleTest.java @@ -16,7 +16,8 @@ void testLargestRectangleHistogram(int[] heights, String expected) { } static Stream histogramProvider() { - return Stream.of(Arguments.of(new int[]{2, 1, 5, 6, 2, 3}, "10"), Arguments.of(new int[]{2, 4}, "4"), Arguments.of(new int[]{4, 4, 4, 4}, "16"), Arguments.of(new int[]{}, "0"), Arguments.of(new int[]{5}, "5"), Arguments.of(new int[]{0, 0, 0}, "0"), Arguments.of(new int[]{6, 2, 5, 4, 5, 1, 6}, "12"), Arguments.of(new int[]{2, 1, 5, 6, 2, 3, 1}, "10"), Arguments.of(createLargeArray(10000, 1), "10000")); + return Stream.of(Arguments.of(new int[] {2, 1, 5, 6, 2, 3}, "10"), Arguments.of(new int[] {2, 4}, "4"), Arguments.of(new int[] {4, 4, 4, 4}, "16"), Arguments.of(new int[] {}, "0"), Arguments.of(new int[] {5}, "5"), Arguments.of(new int[] {0, 0, 0}, "0"), + Arguments.of(new int[] {6, 2, 5, 4, 5, 1, 6}, "12"), Arguments.of(new int[] {2, 1, 5, 6, 2, 3, 1}, "10"), Arguments.of(createLargeArray(10000, 1), "10000")); } private static int[] createLargeArray(int size, int value) { From 86ca17845925601ac793413131b80f853569a09e Mon Sep 17 00:00:00 2001 From: alxkm Date: Tue, 8 Jul 2025 23:38:45 +0200 Subject: [PATCH 3/3] refactor: fix clang formatting issue for test data --- .../java/com/thealgorithms/stacks/LargestRectangleTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/com/thealgorithms/stacks/LargestRectangleTest.java b/src/test/java/com/thealgorithms/stacks/LargestRectangleTest.java index fa4f17bda669..fec5d371c106 100644 --- a/src/test/java/com/thealgorithms/stacks/LargestRectangleTest.java +++ b/src/test/java/com/thealgorithms/stacks/LargestRectangleTest.java @@ -17,7 +17,7 @@ void testLargestRectangleHistogram(int[] heights, String expected) { static Stream histogramProvider() { return Stream.of(Arguments.of(new int[] {2, 1, 5, 6, 2, 3}, "10"), Arguments.of(new int[] {2, 4}, "4"), Arguments.of(new int[] {4, 4, 4, 4}, "16"), Arguments.of(new int[] {}, "0"), Arguments.of(new int[] {5}, "5"), Arguments.of(new int[] {0, 0, 0}, "0"), - Arguments.of(new int[] {6, 2, 5, 4, 5, 1, 6}, "12"), Arguments.of(new int[] {2, 1, 5, 6, 2, 3, 1}, "10"), Arguments.of(createLargeArray(10000, 1), "10000")); + Arguments.of(new int[] {6, 2, 5, 4, 5, 1, 6}, "12"), Arguments.of(new int[] {2, 1, 5, 6, 2, 3, 1}, "10"), Arguments.of(createLargeArray(10000, 1), "10000")); } private static int[] createLargeArray(int size, int value) {