トピックはLeetCodeからです
他のソリューションまたはソースコードにアクセスできます:tongji4m3
解説
所与のn非負整数は、それらは、ヒストグラムの各カラムの高さを表すために使用されます。各ピラーは互いに隣接しており、幅は1です。
ヒストグラムで輪郭を描くことができる長方形の最大領域を見つけます。
例:
输入: [2,1,5,6,2,3]
输出: 10
アイデア
全体的な考え方は、最大の長方形は配列を1回トラバースし、インデックスiによって形成される長方形を高さとして見て、それらの最大値を取ることです。
増加するシーケンスを維持します。減少する要素に遭遇したとき、それよりも前の要素によって形成される可能性のある長方形が決定され、計算できます。次に、配列がトラバースされるまで続行します。その時点で、シーケンスが増加します。
このシーケンスの要素nums [i]の場合、その右側の境界は配列の最後の要素であり、左側の境界は次のスタック要素+1です(検討のためにそれを描画します)
Stack<Integer> stack;//递增序列 存储的是索引下标
for i in N
{
//nums[stack.top()]=nums[i]的要留下,因为前面的元素还可以继续扩展
while(!stack.isEmpty() && nums[stack.top()]>nums[i])
{
//这里计算的是以弹出那个元素为高度的最大矩形
int index=stack.pop();
result=max(result,(i-index)*nums[index]);
}
stack.push(i);//此时为递增序列
}
//对递增序列进行计算
//这些元素每一个都可以扩展到数组尽头
while(!stack.isEmpty())
{
//范围是[ stack.top()+1 , N-1 ]
int index=stack.pop();
result=max(result,(N-stack.top()-1)*nums[index]);
}
細部
- スタックの最下部は-1でマークされます。そうでない場合、インデックス0の要素の左境界を計算する際に問題があります
- 左側の境界の計算は直接iにインデックスを付けることができないことに注意してください(左側より上の要素は無視され、スタック内にないことに注意してください)
- 計算は高いインデックス位置の値に基づいており、左右に拡張できる最大距離は幅であることに注意してください
コード
public int largestRectangleArea(int[] heights)
{
//递增序列 存储的是索引下标
Stack<Integer> stack = new Stack<>();
int result = 0;
int n = heights.length;
//防止最左边元素计算不了面积
stack.push(-1);
for (int i = 0; i < n; i++)
{
//heights[stack.top()]=heights[i]的要留下,因为前面的元素还可以继续扩展
while (stack.peek() != -1 && heights[stack.peek()] > heights[i])
{
//这里计算的是以弹出那个元素为高度的最大矩形
int index = stack.pop();
//look 这里也要按照下面的思路,即该元素的左边界是stack.top()+1 而不能仅仅是(i - index) * heights[index]
result = Math.max(result, (i - stack.peek() - 1) * heights[index]);
}
//此时为递增序列
stack.push(i);
}
//对递增序列进行计算
//这些元素每一个都可以扩展到数组尽头
while (stack.peek() != -1)
{
//范围是[ stack.top()+1 , N-1 ]
int index = stack.pop();
result = Math.max(result, (n - stack.peek() - 1) * heights[index]);
}
return result;
}
複雑さの分析
時間の複雑さ
O(N)O(N) O (N )
スペースの複雑さ
O(N)O(N) O (N )