【力扣】栈与队列专题总结


前言

从2022年12月15日左右开始看代码随想录中的栈与队列章节,到现在为止也算是一刷过了一遍代码随想录中的栈与队列章节,特此写一篇博客记录一下


一、用栈实现队列(力扣232)

1. 思路

首先需要明确的是,栈是先入后出,队列是先入先出,那么通过栈来实现队列的先入先出的操作,需要两个栈,其中一个是输入栈,一个是输出栈
双栈实现队列
在此题里需要实现队列的四个函数:push,pop,peek以及empty

  1. 双栈演示可以发现,对于push来讲,即只需要在stack_in中push一个元素即达到要求
  2. 对于pop弹出队列开头元素操作,其实也就是对于stack_out中的栈顶元素进行弹出即完成操作(如果stack_out没有元素就需要将stack_in中的元素全部移过来)
  3. 对于peek(返回队列开头元素但不弹出),其实和pop差不多的操作性质
  4. empty只需要判断两个栈是否都为空即可

2. 代码实现(js)

代码如下:

var MyQueue = function() {
    this.stackIn = [];
    this.stackOut = [];
};

/** 
 * @param {number} x
 * @return {void}
 */
MyQueue.prototype.push = function(x) {
    this.stackIn.push(x)
};

/**
 * @return {number}
 */
MyQueue.prototype.pop = function() {
    let size = this.stackOut.length
    if(size) {
        return this.stackOut.pop()
    }
    while(this.stackIn.length) {
        this.stackOut.push(this.stackIn.pop())
    }
    return this.stackOut.pop()
};

/**
 * @return {number}
 */
MyQueue.prototype.peek = function() {
    let p
    let size = this.stackOut.length
    if(size) {
        return this.stackOut[this.stackOut.length-1]
    }
    while(this.stackIn.length) {
        this.stackOut.push(this.stackIn.pop())
    }
    return this.stackOut[this.stackOut.length-1]
};

/**
 * @return {boolean}
 */
MyQueue.prototype.empty = function() {
    if(this.stackOut.length==0 && this.stackIn.length == 0) {
        return true
    }
    return false
};

/**
 * Your MyQueue object will be instantiated and called as such:
 * var obj = new MyQueue()
 * obj.push(x)
 * var param_2 = obj.pop()
 * var param_3 = obj.peek()
 * var param_4 = obj.empty()
 */

二、用队列实现栈(力扣225)

1. 思路

队列先入先出,栈先入后出,题目明确要求使用两个队列实现一个栈,实际上两个队列中的一个队列起到的作用是记录的作用。我们记两个队列为que1与que2.
用两个队列que1和que2实现队列的功能,que2其实完全就是一个备份的作用,把que1最后面的元素以外的元素都备份到que2,然后弹出最后面的元素,再把其他元素从que2导回que1。

要实现push,pop,top,empty操作

  1. push:push其实只是将元素入que1队列即可
  2. pop:先把队列末尾以前的元素都移到que2中,而后将que1队列末尾的元素进行弹出,最后将que2中的元素在移回que1中
  3. top:访问到que1中的最末尾元素即可
  4. empty:que1中的长度为0就可以

2. 代码实现(js)

代码如下:

var MyStack = function() {
    this.queIn = []
    this.queOut = []
};

/** 
 * @param {number} x
 * @return {void}
 */
MyStack.prototype.push = function(x) {
    this.queIn.push(x)
};

/**
 * @return {number}
 */
MyStack.prototype.pop = function() {
    while(this.queIn.length>1) {
        this.queOut.push(this.queIn.shift())
    }
    let ans = this.queIn.shift()
    while(this.queOut.length) {
        this.queIn.push(this.queOut.shift())
    }
    return ans
};

/**
 * @return {number}
 */
MyStack.prototype.top = function() {
    return this.queIn.slice(-1)
};

/**
 * @return {boolean}
 */
MyStack.prototype.empty = function() {
    if(this.queIn.length) {
        return false
    }
    return true
};

/**
 * Your MyStack object will be instantiated and called as such:
 * var obj = new MyStack()
 * obj.push(x)
 * var param_2 = obj.pop()
 * var param_3 = obj.top()
 * var param_4 = obj.empty()
 */

三、有效的括号(力扣20)

1. 思路

括号只要是[].{},()互相配对即可,[()]合法,{}([)]不合法
因此遇到左括号进栈,遇到右括号时判断其与栈顶元素(左括号)是否配对即可

2. 代码实现(js)

代码如下:

/**
 * @param {string} s
 * @return {boolean}
 */
var isValid = function(s) {
    let stack = []
    for(let x of s) {
        if(x == '(' || x == '[' || x == '{' ) {
            stack.push(x)
        }else{
            if(x == ')' && stack.pop()!='(') {
                return false
            }
            if(x== '}' && stack.pop()!='{') {
                return false
            }
            if(x== ']' && stack.pop()!='[') {
                return false
            }
        }
    }
    if(stack.length!=0) {
        return false
    }
    return true
};

四、删除字符串中的所有相邻重复项(力扣1047)

1. 思路

一眼其实就可以看出来用栈进行实现,因为是两个重复的字符并进行删除,因此假如第一次遇见元素就将其压入栈中,如果下一个元素与栈顶元素一致,那么我们只需要pop出栈顶元素即可;如果第二次与第一次不一样的话就继续压栈即可,最终返回stack中的内容

2. 代码实现(js)

代码如下:

/**
 * @param {string} s
 * @return {string}
 */
var removeDuplicates = function(s) {
    let stack = []
    for(let i = 0 ; i < s.length ; i++ ){
        if(stack.length && stack[stack.length-1] == s[i]) {
            stack.pop()
        }else {
            stack.push(s[i])
        }
    }
    // console.log(stack)
    return stack.join('')
};

五、逆波兰表达式求值(力扣150)

1. 思路

只要学过数据结构那么对这个表达式都不会陌生,只需要一个数字栈即可,如果遍历到了符号字符,那么取出栈顶的两个元素进行运算,而后将运算结果压栈即可,最终数字栈只剩余一个元素作为其答案(需要注意的是除法和减法是如何进行计算的)【第二个弹出的元素作为被减数(被除数)】

2. 代码实现(js)

代码如下:

/**
 * @param {string[]} tokens
 * @return {number}
 */
var evalRPN = function(tokens) {
    var num = []
    // var sym = []
    for(let i = 0 ; i <tokens.length ; i++) {
        if(tokens[i]!='+'&&tokens[i]!='-'&&tokens[i]!='*'&&tokens[i]!='/') {
            num.push(parseInt(tokens[i]))
        }else{
            let num1 = num.pop()
            let num2 = num.pop()
            if(tokens[i] == '/') {
                let oo = num2/num1
                if(oo<0) {
                    num.push(Math.ceil(oo))
                }else{
                    num.push(Math.floor(oo))
                }
            }
            if(tokens[i] == '+')
                num.push(num1+num2)
            if(tokens[i] == '-')
                num.push(num2-num1)
            if(tokens[i] == '*')
                num.push(num1*num2)
        }
    }
    // console.log(num)
    return num[0]
};

六、滑动窗口(力扣239)

点击这里查看滑动窗口讲解


七、前 K 个高频元素(力扣347)

1. 思路

统计元素次数率先想到哈希表,而后进行统计前k个,涉及到排序,那么可以使用快速排序直接进行对值的排序,而后在对其对应的键按照值的大小进行统计,取出前k个的键即可

2. 代码实现(js)

代码如下:

/**
 * @param {number[]} nums
 * @param {number} k
 * @return {number[]}
 */
var topKFrequent = function(nums, k) {
    let obj = new Map()
    for(let i of nums) {
        if(obj.has(i) == false) {
            obj.set(i , 1)
        }else{
            pp = obj.get(i)
            obj.set(i , pp+1)
        }
    }
    
    var map = Array.from(obj)

    map.sort((a,b)=>{
        return a[1]-b[1]
    })
    let ans = []
    for (var [key,value] of map) {
        ans.push(key)
    }
    let arr = []
    for(let i = ans.length-k ; i <ans.length ; i++) {
        arr.push(ans[i])
    }
    return arr
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值