package main
import (
"errors"
"fmt"
)
/**
栈/队列类型 - 简单题
题目:
设计一个有getMin功能的栈
实现一个特殊的栈,既要实现栈的功能,又要能够实现弹出栈中最小元素的操作(只取一次最小值)
时间复杂度:
pop,push,getMin时间复杂度都是O(1)
设计的栈类型可以使用现成的栈结构
*/
func main() {
fmt.Println("test start")
// 拿到问题先写解
/**
思路:
操作为O(1)的都会消耗较大的空间,所以这种思路朝创建空间去想
栈的特性:压入,弹出,先进后出
双桶最小记录原理:
创建两个桶,压入规则:压入一个数,比最小桶的顶部元素小则两个桶都压入,比最小桶的顶部元素大则只压入到数据桶
弹出规则:需要弹出一个最小的数,则需要对比最小桶和数据桶顶部元素的大小,
如果数据桶顶部元素不等于最小桶顶部元素,则直接弹出数据桶顶部元素
如果数据桶顶部元素等于最小桶顶部元素,则再将最小桶顶部元素也弹出
获取到最小元素
*/
// 测试数据: 1,5,2,6,8,9,4,34,90,56,25
testData := []int64{200, 70, 250, 50, 48, 39, 84, 34, 90, 56, 25}
bucket := NewBucket()
for _, value := range testData{
_ = bucket.Push(value)
}
fmt.Printf("bucketMin:%v|bucketData:%v", bucket.bucketMin, bucket.bucketData)
fmt.Println()
minData, _ := bucket.GetMin()
fmt.Printf("minData: %v", minData)
fmt.Println()
for len(bucket.bucketData) != 0 {
popData, _ := bucket.Pop()
fmt.Printf("pop:%v", popData)
fmt.Println()
}
fmt.Println("test end")
}
/**
双桶最小记录原理实现
*/
type Bucket struct {
bucketMin []int64 // 最小数桶
bucketData []int64 // 所有数据桶
}
// 创建栈
func NewBucket() (bucket *Bucket) {
return &Bucket{
bucketMin: []int64{},
bucketData: []int64{},
}
}
func(b *Bucket) Push(element int64) (err error) {
// 压入数据为最小的时候则将最小桶和数据桶都压入对应的桶内
if len(b.bucketMin) == 0 {
b.bucketMin = append(b.bucketMin, element)
} else if min, _ := b.GetMin(); element <= min {
b.bucketMin = append(b.bucketMin, element)
}
b.bucketData = append(b.bucketData, element)
return nil
}
func(b *Bucket) Pop() (minData int64, err error) {
minLen := len(b.bucketMin)
dataLen := len(b.bucketData)
if dataLen == 0 {
return 0, errors.New("pop Exception")
}
min, err := b.GetMin()
if err != nil {
return 0, errors.New("pop Exception")
}
data := b.bucketData[dataLen - 1]
if min == data {
b.bucketMin = append(b.bucketMin[:minLen - 1], b.bucketMin[minLen:]...)
}
b.bucketData = append(b.bucketData[:dataLen - 1], b.bucketData[dataLen:]...)
return data, nil
}
func(b *Bucket) GetMin() (min int64, err error) {
minLen := len(b.bucketMin)
if minLen == 0 {
return 0, errors.New("GetMin Exception")
}
return b.bucketMin[minLen - 1], nil
}