diff --git a/src/main/java/com/thealgorithms/stacks/LargestRectangle.java b/src/main/java/com/thealgorithms/stacks/LargestRectangle.java
index 006e03632e63..eb222c8c488e 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..fec5d371c106 100644
--- a/src/test/java/com/thealgorithms/stacks/LargestRectangleTest.java
+++ b/src/test/java/com/thealgorithms/stacks/LargestRectangleTest.java
@@ -2,76 +2,27 @@
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;
}
}