beam: largest rectangle in histogram (O(n) stack) with brute-force tests
This commit is contained in:
1 parent
bdebc3ee8c
commit
5c87d5a863
2 files changed
+59
No files matched your search
@@ -0,0 +1,38 @@
|
||||
"""Largest Rectangle in Histogram.
|
||||
|
||||
Given bar heights, find area of largest rectangle using contiguous bars.
|
||||
O(n) via monotonic increasing stack of indices with a sentinel 0.
|
||||
Brute-force oracle included for verification.
|
||||
"""
|
||||
from typing import List
|
||||
|
||||
|
||||
def largest_rectangle_area(heights: List[int]) -> int:
|
||||
if not heights:
|
||||
return 0
|
||||
stack: List[int] = []
|
||||
best = 0
|
||||
h = list(heights) + [0]
|
||||
for i, height in enumerate(h):
|
||||
while stack and h[stack[-1]] > height:
|
||||
idx = stack.pop()
|
||||
left = stack[-1] if stack else -1
|
||||
width = i - left - 1
|
||||
area = h[idx] * width
|
||||
if area > best:
|
||||
best = area
|
||||
stack.append(i)
|
||||
return best
|
||||
|
||||
|
||||
def _brute(heights: List[int]) -> int:
|
||||
n = len(heights)
|
||||
best = 0
|
||||
for i in range(n):
|
||||
mn = heights[i]
|
||||
for j in range(i, n):
|
||||
mn = min(mn, heights[j])
|
||||
area = mn * (j - i + 1)
|
||||
if area > best:
|
||||
best = area
|
||||
return best
|
||||
@@ -0,0 +1,21 @@
|
||||
import random, sys
|
||||
sys.path.insert(0, "/root/.hermes/wizard-outputs/beam")
|
||||
from largest_rect_hist import largest_rectangle_area, _brute
|
||||
|
||||
def test_random():
|
||||
rng = random.Random(2024)
|
||||
for _ in range(5000):
|
||||
n = rng.randint(0, 30)
|
||||
hs = [rng.randint(0, 8) for _ in range(n)]
|
||||
assert largest_rectangle_area(hs) == _brute(hs), hs
|
||||
|
||||
def test_edges():
|
||||
assert largest_rectangle_area([]) == 0
|
||||
assert largest_rectangle_area([2,1,5,6,2,3]) == 10
|
||||
assert largest_rectangle_area([2,4]) == 4
|
||||
assert largest_rectangle_area([1]) == 1
|
||||
assert largest_rectangle_area([0,0,0]) == 0
|
||||
|
||||
test_random()
|
||||
test_edges()
|
||||
print("ALL OK")
|
||||
Reference in new issue
Block a user