栈和队列

需要一个输出栈和输入栈

先将数据放到输入栈,再把数据从输入栈放到输出栈,此时输出栈输出数据的顺序就和队列一样了,先入先出

type MyQueue struct {
    instack []int
    outstack  []int
}


func Constructor() MyQueue {
  return MyQueue{
        instack: make([]int, 0),
        outstack:  make([]int, 0),
}
}

func (this *MyQueue) Push(x int)  {
    this.instack=append(this.instack,x)
}

func (this *MyQueue) intoout(){
    for len(this.instack)>0{
        this.outstack=append(this.outstack,this.instack[len(this.instack)-1])
        this.instack=this.instack[:len(this.instack)-1]
    }
}

func (this *MyQueue) Pop() int {
    if len(this.outstack)==0{
        this.intoout()
    }
        val:=this.outstack[len(this.outstack)-1]
        this.outstack=this.outstack[:len(this.outstack)-1]

    return val
}


func (this *MyQueue) Peek() int {
       if len(this.outstack)==0{
        this.intoout()
    }
    return this.outstack[len(this.outstack)-1]
}


func (this *MyQueue) Empty() bool {
    return len(this.instack)==0&&len(this.outstack)==0
}



方法一:两个队列实现

fig2

type MyStack struct {
    //创建两个队列
    queue1 []int
    queue2 []int
}


func Constructor() MyStack {
    return MyStack{	//初始化
        queue1:make([]int,0),
        queue2:make([]int,0),
    }
}


func (this *MyStack) Push(x int)  {
     //先将数据存在queue2中
    this.queue2 = append(this.queue2,x)	
   //将queue1中所有元素移到queue2中,再将两个队列进行交换
    this.Move() 
}


func (this *MyStack) Move(){    
    if len(this.queue1) == 0{
        //交换,queue1置为queue2,queue2置为空
        this.queue1,this.queue2 = this.queue2,this.queue1
    }else{
        //queue1元素从头开始一个一个追加到queue2中
            this.queue2 = append(this.queue2,this.queue1[0])  
            this.queue1 = this.queue1[1:]	//去除第一个元素
            this.Move()     //重复
    }
}

func (this *MyStack) Pop() int {
    val := this.queue1[0]
    this.queue1 = this.queue1[1:]	//去除第一个元素
    return val

}


func (this *MyStack) Top() int {
    return this.queue1[0]	//直接返回
}


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


/**
 * Your MyStack object will be instantiated and called as such:
 * obj := Constructor();
 * obj.Push(x);
 * param_2 := obj.Pop();
 * param_3 := obj.Top();
 * param_4 := obj.Empty();
 */

方法二:

使用一个队列,在弹栈的时候,只要将队列头部的元素(除了最后一个元素外) 重新添加到队列尾部,此时在去弹出元素就是栈的顺序了。

fig2

type MyStack struct {
    queue []int//创建一个队列
}


/** Initialize your data structure here. */
func Constructor() MyStack {
    return MyStack{   //初始化
        queue:make([]int,0),
    }
}


/** Push element x onto stack. */
func (this *MyStack) Push(x int)  {
    //添加元素
    this.queue=append(this.queue,x)
}


/** Removes the element on top of the stack and returns that element. */
func (this *MyStack) Pop() int {
    n:=len(this.queue)-1//判断长度
    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
    
}


/** Get the top element. */
func (this *MyStack) Top() int {
    //利用Pop函数,弹出来的元素重新添加
    val:=this.Pop()
    this.queue=append(this.queue,val)
    return val
}


/** Returns whether the stack is empty. */
func (this *MyStack) Empty() bool {
    return len(this.queue)==0
}

func isValid(s string) bool {
    queue:=[]byte{}

    m:=map[byte]byte{
       ')' :'(',
       ']': '[',
       '}': '{',
    }
    
    arr:=[]byte(s)
    for _,v:=range arr{
        if v=='('||v=='{'||v=='['{
            queue=append(queue,v)
        }else if v==')'||v=='}'||v==']'{
            if len(queue)==0||queue[len(queue)-1]!=m[v]{
                return false
            }else{
                queue=queue[:len(queue)-1]
            }
        }
    }
    if len(queue)!=0{
        return false
    }else{
           return true 
    }

}

func removeDuplicates(s string) string {
    str:=[]byte(s)
    queue:=make([]byte,0)

    for _,v:=range str{ 
        if len(queue)>0&&queue[len(queue)-1]==v{
            queue=queue[:len(queue)-1]
        }else{
            queue=append(queue,v)
        }
    }
    return string(queue)

}

func evalRPN(tokens []string) int {

queue:=make([]int,0)

for _,v:=range tokens{
    if v=="+"||v=="-"||v=="/"||v=="*"{
       
        num1,num2 := queue[len(queue)-2], queue[len(queue)-1]
        queue=queue[:len(queue)-2]
        switch v{
            case "+":
            queue=append(queue,num1+num2)
            case "-":
             queue=append(queue,num1-num2)
            case "/":
              queue=append(queue,num1/num2)
            case "*":
              queue=append(queue,num1*num2)
        }
   
    }else{
        n,_:=strconv.Atoi(v)
        queue=append(queue,n)
    }
}

return queue[0]

}

单调队列实现

单调队列思想:

队列没有必要维护窗口里的所有元素,只需要维护有可能成为窗口里最大值的元素就可以了,同时保证队列里的元素数值是由大到小的

单调队列不是单纯的给队列中元素排序,那和优先级队列没有什么区别了。


设计时要注意的

  • pop(value):如果窗口移除的元素value等于单调队列的出口元素,那么队列弹出元素,否则不用任何操作
  • push(value):如果push的元素value大于入口元素的数值,那么就将队列出口的元素弹出,直到push元素的数值小于等于队列入口元素的数值为止
type MyQueue struct{   //创建结构体
    queue []int
}

func NewMyQueue() *MyQueue {    //初始化函数
    return &MyQueue{
        queue: make([]int, 0),
    }
}

func (m *MyQueue) Push(k int){
    //将单调队列中比k小的全都弹出
    if len(m.queue)>0 && k>m.queue[0]{  //队列中所有的元素都比k小
        m.queue=[]int{}
    }
    for len(m.queue)>0 && m.queue[len(m.queue)-1]<k{   // 队列中所可能存在元素比k小    
        m.queue=m.queue[:len(m.queue)-1]
    }
    m.queue=append(m.queue,k)
}

func (m *MyQueue) Pop(t int){  
    if m.queue[0]==t{   //判断滑动窗口最左边元素t是不是单调队列最大值,若是弹出,否则什么都不用做
        m.queue=m.queue[1:]
    }
}

func maxSlidingWindow(nums []int, k int) []int {
   queue:=NewMyQueue()
    arr:=make([]int,0)
    left,right:=0,k-1

    for i:=left;i<=right;i++{
        queue.Push(nums[i])
    }
    arr=append(arr,queue.queue[0])

    right++ 
    for right<=len(nums)-1{
         queue.Pop(nums[left])
        queue.Push(nums[right])
        arr=append(arr,queue.queue[0])
        left++
        right++
    }

    return arr

}

用了 heap 库

func topKFrequent(nums []int, k int) []int {
    map_num:=map[int]int{}
    //记录每个元素出现的次数
    for _,item:=range nums{
        map_num[item]++
    }
    h:=&IHeap{}
    heap.Init(h)
    //所有元素入堆,堆的长度为k
    for key,value:=range map_num{
        heap.Push(h,[2]int{key,value})
        if h.Len()>k{
            heap.Pop(h)
        }
    }
    res:=make([]int,k)
    //按顺序返回堆中的元素
    for i:=0;i<k;i++{
        res[k-i-1]=heap.Pop(h).([2]int)[0]
    }
    return res
}

//构建小顶堆
type IHeap [][2]int

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

func (h IHeap) Less (i,j int) bool {
    return h[i][1]<h[j][1]
}

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

func (h *IHeap) Push(x interface{}){
    *h=append(*h,x.([2]int))
}
func (h *IHeap) Pop() interface{}{
    old:=*h
    n:=len(old)
    x:=old[n-1]
    *h=old[0:n-1]
    return x
}

/构建小顶堆
type IHeap [][2]int

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

func (h IHeap) Less (i,j int) bool {
return h[i][1]<h[j][1]
}

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

func (h *IHeap) Push(x interface{}){
*h=append(*h,x.([2]int))
}
func (h *IHeap) Pop() interface{}{
old:=*h
n:=len(old)
x:=old[n-1]
*h=old[0:n-1]
return x
}