【Python】ヒストグラムの下に形成できる最大の長方形の面積を求めるプログラム
ヒストグラムの各棒の高さを表す数値のリストが与えられます。このとき、棒の下に形成できる最大の長方形の面積を求める問題を考えてみましょう。
例えば、入力が nums = [3, 2, 5, 7] の場合を見てみます。
この場合の出力は 10 になります。高さ2の棒が幅5にわたって連続しているため、2 × 5 = 10 が最大の面積となります。
解法のアプローチ:スタックを使った効率的なアルゴリズム
この問題は、単調増加スタックを利用することで O(n) の時間計算量で効率的に解けます。各棒について「その高さを維持できる最大の幅」を計算し、面積の最大値を更新していくのが基本の考え方です。
具体的な手順は以下の通りです。
- スタックの初期化: 空のスタック stk を作成し、番兵(境界マーカー)として最初に -1 を挿入します。
- 番兵の追加: heights の末尾に 0 を挿入します。これにより、ループの終了時に残っているすべての棒を強制的に処理できるようになります。
- 答えの初期化: 変数 ans を 0 で初期化します。
- 各棒の走査: i を 0 から heights のサイズまで繰り返し、以下を処理します。
- heights[i] がスタックの先頭が指す高さより小さい間、次を繰り返します。
- h := スタックの先頭が指す高さを取得し、スタックからポップする
- w := i − スタックの新しい先頭 − 1(長方形の幅を計算)
- ans := ans と (h × w) のうち大きい方を採用する
- インデックス i をスタックにプッシュします。
- heights[i] がスタックの先頭が指す高さより小さい間、次を繰り返します。
- 結果の返却: 最終的な ans を返します。
それでは、理解を深めるために実際の実装を見てみましょう。
実装例
class Solution:
def solve(self, heights):
stk = [-1]
heights.append(0)
ans = 0
for i in range(len(heights)):
while heights[i] < heights[stk[-1]]:
h = heights[stk.pop()]
w = i - stk[-1] - 1
ans = max(ans, h * w)
stk.append(i)
return ans
ob = Solution()
nums = [3, 2, 5, 7]
print(ob.solve(nums))
入力
[3, 2, 5, 7]
出力
10
計算量について
このアルゴリズムでは、各インデックスはスタックに一度プッシュされ、一度だけポップされるため、時間計算量は O(n) です。また、使用しているのはスタックのみなので、空間計算量も O(n) に抑えられます。全組み合わせを総当たりで調べる O(n²) の素朴な手法と比べて、大規模な入力でも高速に動作する点が大きなメリットです。
-
Pythonで配列内の最大の要素を見つける方法を解説
この記事では、「配列の中から最大の要素を求める」という問題の解決方法について詳しく解説します。 問題の概要 問題文:与えられた配列に対して、その中で最も大きい要素を計算して求める必要があります。 ここではブルートフォース(総当たり)アプローチを使用します。これは、配列全体を先頭から順番に走査しながら各要素を比較し、その時点での最大値を更新していくというシンプルかつ確実な手法です。 実装例 以下に具体的なコードを示します。 # 最大値を求める関数 def largest(arr, n): # 最大要素の初期値として最初の要素を設定 max = arr[0] # 配列全体を
-
Pythonで配列内の最大要素を見つける方法【初心者向け解説】
本記事では、配列の中から最大の要素を見つけるための解法とアプローチについて詳しく解説します。 問題の概要 配列が入力として与えられたとき、その中から最も大きい要素を見つけ出すことが課題となります。 アプローチ この問題は「線形探索」と呼ばれるシンプルな手法で解決できます。手順は以下の通りです。 まず、変数 max を配列の最初の要素で初期化します。 次に、2番目の要素から配列の末尾まで順番に走査していきます。 走査中の各要素について、現在の max の値と比較します。 要素が max より大きければ、max の値をその要素で更新します。 そうでなければ、そのまま次の要素へ進みます。 この処