栈不仅是经典的数据结构还是很多算法题的解法。
题目一:225. 用队列实现栈
tips: 注意队列是先进先出,尾进头出。栈的pop操作要将尾部的元素移动到首部,然后取出。
// 用队列实现栈
func Constructor() MyStack {
return MyStack{
queue: make([]int, 0),
}
}
func (this *MyStack) Push(x int) {
this.queue = append(this.queue, x)
}
func (this *MyStack) Pop() int {
if this.Empty() {
return 0
}
n := len(this.queue) - 1
//队列是先进先出,尾进头出,因此只能从queue头部取值,将尾部的值放到头部即可
for n != 0 {
val := this.queue[0]
this.queue = this.queue[1:]
this.queue = append(this.queue, val)
n--
}
val := this.queue[0]
this.queue = this.queue[1:]
return val
}
func (this *MyStack) Top() int {
val := this.Pop()
if val != 0 {
this.queue = append(this.queue, val)
}
return val
}
func (this *MyStack) Empty() bool {
if len(this.queue) == 0 {
return true
}
return false
}
题目二:155. 最小栈
tips: 维护一个当前元素对应的最小值的栈。 stack:[2,3,4,4,5,6,1,7,2],min_stack:[2,2,2,2,2,2,1,1,1]
// 155. 最小栈
type MinStack struct {
stack []int
minStack []float64
}
func MinStackConstructor() MinStack {
return MinStack{
stack: []int{},
minStack: []float64{math.MaxFloat64},
}
}
func (this *MinStack) Push(x int) {
this.stack = append(this.stack, x)
top := this.minStack[len(this.minStack)-1]
this.minStack = append(this.minStack, math.Min(float64(x), top))
}
func (this *MinStack) Pop() {
this.stack = this.stack[:len(this.stack)-1]
this.minStack = this.minStack[:len(this.minStack)-1]
}
func (this *MinStack) Top() int {
return this.stack[len(this.stack)-1]
}
func (this *MinStack) GetMin() int {
return int(this.minStack[len(this.minStack)-1])
}
题目三:739. 每日温度
tips: 需要找到左边或者右边第一个比当前位置的大或者小的题目,则可以考虑使用单调栈。
// 739. 每日温度
// 时间复杂度O(n)
// 空间复杂度O(n)
func dailyTemperatures(temperatures []int) []int {
if len(temperatures) == 0 {
return nil
}
var res = make([]int, len(temperatures))
var stack []int
for i, t := range temperatures {
for len(stack) > 0 && t > temperatures[stack[len(stack)-1]] {
preIndex := stack[len(stack)-1]
res[preIndex] = i - preIndex
stack = stack[:len(stack)-1]
}
stack = append(stack, i)
}
return res
}
题目四:151. 反转字符串中的单词
tips: 需要反转顺序的时候,可以考虑使用栈。
// 151. 反转字符串中的单词
func reverseWords(s string) string {
var stack []string
idx := 0
for idx < len(s) {
for idx < len(s) && s[idx] == ' ' {
idx++
}
if idx == len(s) {
break
}
left := idx
for idx < len(s) && s[idx] != ' ' {
idx++
}
stack = append(stack, s[left:idx])
}
wordsBuilder := strings.Builder{}
for i := len(stack) - 1; i >= 0; i-- {
wordsBuilder.WriteString(stack[i])
if i != 0 {
wordsBuilder.WriteString(" ")
}
}
return wordsBuilder.String()
}
题目五:20. 有效的括号
tips: 需要考虑左右匹配的时候,可以考虑使用栈。
// 20. 有效的括号
func isValid(s string) bool {
stack := []string{string(s[0])}
l := len(stack)
for i, c := range s {
if i == 0 {
continue
}
stack = append(stack, string(c))
l = len(stack)
for l > 1 && (stack[l-1] == ")" && stack[l-2] == "(" ||
stack[l-1] == "]" && stack[l-2] == "[" ||
stack[l-1] == "}" && stack[l-2] == "{") {
stack = stack[0 : l-2]
l = len(stack)
}
}
if l == 0 {
return true
}
return false
}
题目六:394. 字符串解码
tips: 依次按照某种匹配规则(字符对,包括空格符)对某块单元处理,可以考虑使用栈。
// 394. 字符串解码
func decodeString(s string) string {
var stack []byte
for i := range s {
if s[i] != ']' {
stack = append(stack, s[i])
} else {
j := len(stack) - 1
for j >= 0 {
if stack[j] == '[' {
break
}
j--
}
// 字符块
temp := make([]byte, len(stack)-j-1)
copy(temp, stack[j+1:])
k := j
j--
for j >= 0 {
if stack[j] < '0' || stack[j] > '9' {
break
}
j--
}
// 字符块前的数字
cnt, _ := strconv.Atoi(string(stack[j+1 : k]))
stack = stack[0 : j+1]
for cnt > 0 {
stack = append(stack, temp...)
cnt--
}
}
}
return string(stack)
}