在Go (Golang)中运用短板效应的实例——捕获雨水

116 阅读2分钟

概述

有一组条形图,每个条形图的宽度为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