概述
有一组条形图,每个条形图的宽度为1个单位,但高度不同,放在旁边。条形的高度用一个数组来表示
[2, 0 , 2, 1, 3, 1]
该数组表示
-
条形的总数是5
-
第一根柱子的高度是2
-
第二根柱子的高度是0
-
第三条的高度是2
-
第四根柱子的高度是1
-
第五根柱子的高度是3
-
第六根柱子的高度是1
我们的目标是找出这些条形图中可容纳的最大水量。

从上图中可以看出
-
第1条和第3条之间可以夹带2个单位的水
-
在第3条和第6条之间可以截留1个单位的水
因此,总共可以困住3个单位的水
让我们看看同样的程序。其策略是使用堆栈:
-
遍历给定的数组
-
对于当前元素,不断从堆栈中弹出,直到堆栈是空的或最上面的元素的高度大于当前元素的高度。
-
对于每一个弹出的元素,计算弹出的元素和当前元素之间可以困住的水。
-
最后,将当前元素推到堆栈中,循环往复,直到数组中的所有元素都被遍历。
程序
package main
import (
"fmt"
"sync"
)
func main() {
output := trap([]int{2, 0, 2, 1, 3, 1})
fmt.Println(output)
output = trap([]int{0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1})
fmt.Println(output)
output = trap([]int{4, 2, 0, 3, 2, 5})
fmt.Println(output)
}
func trap(height []int) int {
output := 0
heightArrayLen := len(height)
customStack := customStack{
stack: make([]int, 0),
}
customStack.Push(0)
for i := 1; i < heightArrayLen; i++ {
for customStack.Size() != 0 {
front, _ := customStack.Front()
if height[front] <= height[i] {
output = output + (i-front-1)*(height[front]-max(height, front+1, i-1))
customStack.Pop()
} else {
output = output + (i-front-1)*(height[i]-max(height, front+1, i-1))
break
}
}
customStack.Push(i)
}
return output
}
func max(input []int, start, end int) int {
if start > end {
return 0
}
max := 0
for i := start; i <= end; i++ {
if input[i] > max {
max = input[i]
}
}
return max
}
type customStack struct {
stack []int
lock sync.RWMutex
}
func (c *customStack) Push(name int) {
c.lock.Lock()
defer c.lock.Unlock()
c.stack = append(c.stack, name)
}
func (c *customStack) Pop() error {
len := len(c.stack)
if len > 0 {
c.lock.Lock()
defer c.lock.Unlock()
c.stack = c.stack[:len-1]
return nil
}
return fmt.Errorf("Pop Error: Stack is empty")
}
func (c *customStack) Front() (int, error) {
len := len(c.stack)
if len > 0 {
c.lock.Lock()
defer c.lock.Unlock()
return c.stack[len-1], nil
}
return 0, fmt.Errorf("Peep Error: Stack is empty")
}
func (c *customStack) Size() int {
return len(c.stack)
}
func (c *customStack) Empty() bool {
return len(c.stack) == 0
}
输出
3
6
9