【代码随想录——栈与队列】

1.栈和队列理论基础

栈和队列的原理大家应该很熟悉了,队列是先进先出,栈是先进后出。
在这里插入图片描述

2.用栈实现队列

在这里插入图片描述

type MyQueue struct {
	head []int
	headSize int
	store []int
	storeSize int
}


func Constructor() MyQueue {
	return MyQueue{
		head : make([]int,100),
		headSize : 0,
		store : make([]int,100),
		storeSize : 0,
	}
}


func (this *MyQueue) Push(x int)  {
	this.store[this.storeSize] = x
	this.storeSize++
}


func (this *MyQueue) Pop() int {
	if this.headSize==0{
		//需要将store中的数倒过来
		for i:=this.storeSize;i>0;{
            i--
			this.head[this.headSize]=this.store[i]
            this.headSize++
		}
		this.storeSize = 0
	}
	if this.headSize>0{
		this.headSize--
		return  this.head[this.headSize]
	}
	return -1
}


func (this *MyQueue) Peek() int {
	if this.headSize==0{
		//需要将store中的数倒过来
		for i:=this.storeSize;i>0;{
            i--
			this.head[this.headSize]=this.store[i]
            this.headSize++
		}
		this.storeSize = 0
	}
	if this.headSize>0{
		return  this.head[this.headSize-1]
	}
	return -1
}


func (this *MyQueue) Empty() bool {
	return this.headSize==0&&this.storeSize==0
}

3.用队列实现栈

在这里插入图片描述

type MyStack struct {
    store []int
    size int
}

func remove(s []int, i int) []int {
    s[i] = s[len(s)-1]
    return s[:len(s)-1]
}

func Constructor() MyStack {
    return MyStack{make([]int,100),0}
}

func (this *MyStack) Push(x int)  {
    this.store[this.size]=x
    this.size++
}

func (this *MyStack) Pop() int {
    this.size--
    return this.store[this.size]
}

func (this *MyStack) Top() int {
    return this.store[this.size-1]
}

func (this *MyStack) Empty() bool {
    return this.size==0
}

4.有效的括号

在这里插入图片描述

func isValid(s string) bool {
	stack := Stack{}
	for i := 0; i < len(s); i++ {
		println(s[i])
		if s[i] == 40 || s[i] == 91 || s[i] == 123 {
			stack.Push(int(s[i]))
		} else {
			char, err := stack.Top()
			if err != nil {
				return false
			}
			if char == 40 && s[i] == 41 {
				stack.Pop()
				continue
			}
			if char == 91 && s[i] == 93 {
				stack.Pop()
				continue
			}
			if char == 123 && s[i] == 125 {
				stack.Pop()
				continue
			}
			return false
		}
	}
	if stack.Len() != 0 {
		return false
	}
	return true
}

type Stack []int

func (stack Stack) Len() int {
	return len(stack)
}

func (stack Stack) IsEmpty() bool {
	return len(stack) == 0
}

func (stack Stack) Cap() int {
	return cap(stack)
}

func (stack *Stack) Push(value int) {
	*stack = append(*stack, value)
}

func (stack Stack) Top() (int, error) {
	if len(stack) == 0 {
		return -1, errors.New("Out of index, len is 0")
	}
	return stack[len(stack)-1], nil
}

func (stack *Stack) Pop() (int, error) {
	theStack := *stack
	if len(theStack) == 0 {
		return -1, errors.New("Out of index, len is 0")
	}
	value := theStack[len(theStack)-1]
	*stack = theStack[:len(theStack)-1]
	return value, nil
}

5.删除字符串中的所有相邻重复项

在这里插入图片描述

func removeDuplicates(s string) string {
	chars := []byte(s)
	p1 := 0
	for i := 0; i < len(chars); i++ {
		if(p1>0 && chars[p1-1]==chars[i]){
			p1--
		}else{
			chars[p1] = chars[i]
			p1++
		}
	}
	return string(chars[:p1])
}

6.逆波兰表达式求值

在这里插入图片描述

func evalRPN(tokens []string) int {
    numIndex := -1
    numArr := make([]int,10000)
    for _,str := range(tokens){
        num, err := strconv.Atoi(str)
        if err==nil{
            //说明是数字
            numIndex++
            numArr[numIndex]=num
        }else{
            //说明是一个+-*/中的一种
            num1 := numArr[numIndex]
            numIndex--
            num2 := numArr[numIndex]
            switch str{
                case "+":
                    numArr[numIndex]=num1+num2
                case "-":
                    numArr[numIndex]=num2-num1
                case "*":
                    numArr[numIndex]=num1*num2
                case "/":
                    numArr[numIndex]=num2/num1
            }
        }
    }
    return numArr[0]
}

7.滑动窗口最大值

在这里插入图片描述
这道题目需要使用单调队列

// 封装单调队列的方式解题
// 那么这个维护元素单调递减的队列就叫做单调队列
// 即单调递减或单调递增的队列
type MyQueue struct {
	queue []int
}

func NewMyQueue() *MyQueue {
	return &MyQueue{
		queue: make([]int, 0),
	}
}

func (m *MyQueue) Front() int {
	return m.queue[0]
}

func (m *MyQueue) Back() int {
	return m.queue[len(m.queue)-1]
}

func (m *MyQueue) Empty() bool {
	return len(m.queue) == 0
}

// push(value):如果push的元素value大于入口元素的数值,那么就将队列入口的元素弹出,直到push元素的数值小于等于队列入口元素的数值为止
func (m *MyQueue) Push(val int) {
	for !m.Empty() && val > m.Back() {
		m.queue = m.queue[:len(m.queue)-1]
	}
	m.queue = append(m.queue, val)
}

// pop(value):如果窗口移除的元素value等于单调队列的出口元素,那么队列弹出元素,否则不用任何操作
func (m *MyQueue) Pop(val int) {
	if !m.Empty() && val == m.Front() {
		m.queue = m.queue[1:]
	}
}

func maxSlidingWindow(nums []int, k int) []int {
	queue := NewMyQueue()
	length := len(nums)
	res := make([]int, 0)
	// 先将前k个元素放入队列
	for i := 0; i < k; i++ {
		queue.Push(nums[i])
	}
	// 记录前k个元素的最大值
	res = append(res, queue.Front())
	for i := k; i < length; i++ {
		// 滑动窗口移除最前面的元素
		queue.Pop(nums[i-k])
		// 滑动窗口添加最后面的元素
		queue.Push(nums[i])
		// 记录最大值
		res = append(res, queue.Front())
	}
	return res
}

8.前K个高频元素

在这里插入图片描述
这题目需要实现go中提供的heap的接口。使用大顶堆即可完成任务。

func topKFrequent(nums []int, k int) []int {
	items := make(map[int]*Item, 0)
	for i := 0; i < len(nums); i++ {
		item, ok := items[nums[i]]
		if !ok {
			items[nums[i]] = &Item{key: nums[i], value: 1}
		} else {
			item.value++
		}
	}

	hp := &ItemHeap{}
	heap.Init(hp)
	for _, value := range items {
		heap.Push(hp, *value)
	}

	res := make([]int, k)
	for i := 0; i < k; i++ {
		item := heap.Pop(hp)
		res[i] = item.(Item).key
	}
	return res
}


//大顶堆
type Item struct {
	// 排序的关键词
	key int
	// value,用来记录出现的次数
	value int
}

type ItemHeap []Item

func (h ItemHeap) Len() int {
	return len(h)
}

func (h ItemHeap) Swap(i, j int) {
	h[i], h[j] = h[j], h[i]
}

func (h ItemHeap) Less(i, j int) bool {
	return h[i].value > h[j].value
}

// 实现heap.Interface接口定义的额外方法
func (h *ItemHeap) Push(item interface{}) {
	*h = append(*h, item.(Item))
}

// 这个方法不是给用户使用的
func (h *ItemHeap) Pop() interface{} {
	old := *h
	n := len(old)
	x := old[n-1]
	*h = old[0 : n-1]
	return x
}
  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值