我正在研究下面的算法难题,这是详细的问题陈述。
找到直方图的最大矩形;例如,给定histogram = [2,1,5,6,2,3],算法应返回10.
我正在处理以下版本的代码。我的问题是,我认为i-nextTop-1
可以被i-top
取代,但在某些测试用例中(例如[2,1,2]),它们会有不同的结果(i-nextTop-1
总会产生正确的结果)。我认为逻辑上他们应该是一样的,并且想知道i-nextTop-1
不等于i-top
class Solution {
public:
int largestRectangleArea(vector<int>& height) {
height.push_back(0);
int result=0;
stack<int> indexStack;
for(int i=0;i<height.size();i++){
while(!indexStack.empty()&&height[i]<height[indexStack.top()]){
int top=indexStack.top();
indexStack.pop();
int nextTop=indexStack.size()==0?-1:indexStack.top();
result=max((i-nextTop-1)*height[top],result);
}
indexStack.push(i);
}
return result;
}
};
答案 0 :(得分:6)
出现i-nextTop-1 != i-top
的情况是以下情况:
nextTop != top-1
这可以通过简单地重新排列不等式i-nextTop-1 != i-top
中的术语来看出。
了解何时发生这种情况的关键在于代码中的以下行,您可以在其中定义nextTop
的值:
int nextTop = indexStack.size() == 0 ? -1 : indexStack.top();
在这里,您说如果indexStack
为空(在前一行代码的pop()
之后),则将nextTop
设置为-1
;否则将nextTop
设置为当前indexStack.top()
。
所以nextTop == top-1
出现时的唯一时间
indexStack
为空且top == 0
或indexStack.top() == top - 1
。在这些情况下,这两种方法总是一致的。在所有其他情况下,他们不会同意,并会产生不同的结果。
您可以通过打印底部每次迭代的i
,nextTop
,(i - top)
,(i - nextTop - 1)
和result
的值来查看发生的情况while
循环。向量{5, 4, 3, 2, 1}
工作正常,但{ 1, 2, 3, 4, 5}
在用i-nextTop-1
替换i-top
时没有。
外部for
循环一次迭代一个直方图元素。元素从左到右被压入堆栈,并且在进入while
循环时,堆栈顶部包含当前元素之前(或仅在其左侧)的元素。 (这是因为当前元素在循环回到顶部之前被推到for
循环底部的堆栈上。)
当算法确定已经考虑了包含该元素的最佳解决方案时,会在while
循环中弹出一个元素。
内部while
循环将继续迭代height[i] < height[indexStack.top()]
,也就是说,只要当前元素的高度小于堆栈顶部元素的高度
在while
循环的每次迭代开始时,堆栈上的元素表示当前元素左边的所有连续元素,它们大于当前元素。
这允许算法计算左边最大矩形的区域,包括当前元素。此计算在以下两行代码中完成:
int nextTop = indexStack.size() == 0 ? -1 : indexStack.top();
result = max((i - nextTop - 1) * height[top], result);
变量i
是当前直方图元素的索引,表示当前计算的矩形的最右边。
变量nextTop
表示矩形最左边的索引。
表达式(i - nextTop - 1)
表示矩形的水平宽度。 height[top]
是矩形的垂直高度,因此result
是这两个术语的乘积。
每个新result
是新计算中的较大者和result
的先前值。