スタックで棒グラフの中に入るいちばん大きい長方形を求める

幅 1 の棒を並べた棒グラフの中に描ける、いちばん大きい長方形の面積を求めます。高さが上がっていく棒をスタックに積み、低い棒が来たら、取り出した棒の高さで左右に広げた長方形を測る、単調スタックの練習です。

海外で定番の問題リスト 4 本には入っていません

問題

幅 1 の棒を隙間なく左から並べた棒グラフの、棒の高さを整数の並び heights で受け取ります。棒グラフの中 (棒の上の空いた所にははみ出さない) に、辺が縦と横の長方形を 1 つ描くとき、いちばん大きい面積を返す関数を書いてください。

  • 長方形は、続いた何本かの棒にまたがってかまいません。高さは、またがる棒のうちいちばん低い棒の高さまでです
  • heights の長さは 1 以上 100000 以下で、値は 0 以上 10000 以下です

入力と出力の例

例 1

2 本目と 3 本目の、高さ 4 と 5 の棒にまたがる、高さ 4、幅 2 の長方形が最も大きく、面積は 8 です。

heights = [2, 4, 5, 1, 3]
8

例 2

同じ高さの棒が 3 本です。3 本全部にまたがる、高さ 3、幅 3 の長方形で、面積は 9 です。

heights = [3, 3, 3]
9

例 3

高い棒 1 本ずつの面積は 2 です。低いまん中の棒の高さ 1 で 3 本全部にまたがると、面積 3 になって、こちらが大きくなります。

heights = [2, 1, 2]
3

面接での聞かれ方

面接では、難しい問いの代表として出されることがあります。

  • 「ヒストグラムの中の最大の長方形の面積を求めてください」
  • 「O(n²) の答えはすぐ書けますか? そこから O(n) にできますか?」と、段を踏んで詰められます
  • 2 次元の 0 と 1 の表で、1 だけでできた最大の長方形を求める問いの、下ごしらえとして出されることもあります

全部の組を調べる書き方を言ってから、「棒ごとに、その高さで左右にどこまで広げられるか」と言い換えると、単調スタックへの道が見えます。

ヒント

まだ開いていません

付箋は 4 枚。下の段ほど答えに近づきます

  1. ヒント 2

  2. ヒント 3

  3. ヒント 4答えに近い

アルゴリズムのチートシートの「スタックとキュー」に、この型の要点を表とコードでまとめています。

スタックは後から入れた物を先に、キューは先に入れた物を先に取り出します。括弧の対応や、順番待ちの処理の形です。

main.py
def largest_rect(heights: list[int]) -> int:
    """
    Goal: 何を返すか

    idea1: まず思いつく案
    -> runtime: O(?)  space: O(?)

    idea2: もっと速い案
    -> runtime: O(?)  space: O(?)

    edge case: 空、1 つだけ、など
    """
    # ここに書きます
    pass


# 「実行」を押すと、この行の結果が出ます
print(largest_rect([2, 4, 5, 1, 3]))

できているか「例で確かめる」を押すと、問題の例を全部この関数に渡して、通ったかをここに出します