Files
obsidian/АиСД/Задачи/LeetCode/Largest Rectangle In Histogram.md
T
roma-dxunvrs 00b700a410 14.09.26
2026-09-14 20:07:06 +03:00

2.9 KiB

Leetcode #84 | #Hard | Монотонный стек | Математика

Идея

Для каждого прямоугольника нам надо найти слева и справа соседей, до которых можно растянуть текущий прямоугольник (например, высота 7, мы находим соседей, пока они >=7). Это можно сделать либо через двойной цикл за квадратичную сложность, либо через монотонный стек. Идем по высотам, если стек пуст - просто ложим. Если текущая высота больше либо равна последней высоте из стека, то пушим ее в стек (можно растянуть), если меньше, то запускаем цикл. Пока текущая высота меньше чем высота на вершине стека, то для вершины стека мы нашли правую границу, а левая - лежит строго под этой высотой в стеке - в силу монотонного стека. Высота равна высоте с вершины стека, ширина i-stack.peek()-1, либо i (если стек пустой) - здесь stack.peek() это высота левой границы. Дальше обновялем результат, после цикла пушим в стек. В конце могли остаться столбцы, для которых не нашлось правых границ. Просто запустим цикл с аналогичными действиями, но только правая граница heights.length-stack.peek()-1, либо heights.length

Big-O

  • Время O(N)
  • Память O(N)

Код

class Solution {
    public int largestRectangleArea(int[] heights) {
        Deque<Integer> stack = new ArrayDeque<>();
        int res = 0;

        for (int i = 0; i < heights.length; i++) {
            while (stack.size() > 0 && heights[i] < heights[stack.peek()]) {
                int height = heights[stack.pop()];
                int weight;

                if (stack.size() == 0) {
                    weight = i;
                } else {
                    weight = i-stack.peek()-1;
                }

                res = Math.max(res, height*weight);
            }
            stack.push(i);
        }

       while (stack.size() > 0) {
            int height = heights[stack.pop()];
            int weight;

            if (stack.size() == 0) {
                weight = heights.length;
            } else {
                weight = heights.length-stack.peek()-1;
            }

            res = Math.max(res, height*weight);
        }
    
        return res;
    }
}