概述
有一组条形图,每个条形图的宽度为1个单位,但高度不同,放在旁边。条形的高度用一个数组来表示
[2, 0 , 2, 1, 3, 1]
该数组表示
-
条形的总数是5
-
第一根柱子的高度是2
-
第二根柱子的高度是0
-
第三条的高度是2
-
第四根柱子的高度是1
-
第五根柱子的高度是3
-
第六根柱子的高度为1
我们的目标是找到直方图中最大的矩形区域。从图中可以看出,最大的矩形区域是4。

下面是我们可以采取的方法来解决这个问题。我们将使用堆栈,假设条形图完全包含在最大的矩形区域内,将找出条形图每个索引的面积。
-
将给定数组的第一个元素推到堆栈中。遍历给定的数组。对于每个条形,我们需要找出左边最近的小条形和右边最近的小条形。
-
对于当前元素,检查顶部元素的高度是否大于当前元素的高度
-
如果是,那么当前元素就是右边最近的小条。而在堆栈中位于顶部元素之后的元素是左侧最近的小条。
-
弹出这个元素并计算最大的矩形区域,假设条形图被完全包括在内。追踪最大的矩形区域
-
重复以上两个步骤,直到堆栈为空或顶层元素的高度小于当前元素。
-
将当前元素推到堆栈中
-
最后返回最大的矩形区域。
程序
以下是相同的程序。
package main
import "fmt"
type customStack struct {
stack []int
}
func (c *customStack) Push(num int) {
c.stack = append(c.stack, num)
}
func (c *customStack) Pop() (int, error) {
length := len(c.stack)
poppedItem := 0
if length > 0 {
poppedItem = c.stack[length-1]
c.stack = c.stack[:length-1]
return poppedItem, nil
}
return 0, fmt.Errorf("stack is empty")
}
func (c *customStack) Front() (int, error) {
length := len(c.stack)
if length > 0 {
return c.stack[length-1], nil
}
return 0, fmt.Errorf("stack is empty")
}
func (c *customStack) Size() int {
return len(c.stack)
}
func largestRectangleArea(heights []int) int {
customStack := &customStack{}
lenHeights := len(heights)
customStack.Push(0)
maxRectangleSize := heights[0]
for i := 1; i < lenHeights; i++ {
for customStack.Size() != 0 {
current, _ := customStack.Front()
if heights[current] > heights[i] {
var rectangleUsingCurrentBar int
current, _ := customStack.Pop()
//Calcualte max rectangle using the current front
previous, err := customStack.Front()
if err != nil {
previous = -1
}
rectangleUsingCurrentBar = (i - previous - 1) * heights[current]
if rectangleUsingCurrentBar > maxRectangleSize {
maxRectangleSize = rectangleUsingCurrentBar
}
} else {
break
}
}
customStack.Push(i)
}
front, err := customStack.Front()
if err != nil {
return maxRectangleSize
}
var rectangleUsingCurrentBar int
for customStack.Size() != 0 {
current, _ := customStack.Pop()
previous, err := customStack.Front()
if err != nil {
previous = -1
}
rectangleUsingCurrentBar = (front - previous) * heights[current]
if rectangleUsingCurrentBar > maxRectangleSize {
maxRectangleSize = rectangleUsingCurrentBar
}
}
return maxRectangleSize
}
func main() {
output := largestRectangleArea([]int{2, 0, 2, 1, 3, 1})
fmt.Println(output)
}
输出
4