栈队列算法整理

47 阅读2分钟

用栈实现队列

  • leetcode.cn/problems/im…

  • 队列先进先出 用一个栈模拟入队,一个栈记录出队

  • var MyQueue = function() {
        this.stack1 = []
        this.stack2 = []
    };
    
    /** 
     * @param {number} x
     * @return {void}
     */
    MyQueue.prototype.push = function(x) {
        this.stack1.push(x)
    };
    
    /**
     * @return {number}
     */
    MyQueue.prototype.pop = function() {
        let len = this.stack2.length
        if(len) return this.stack2.pop()
        while(this.stack1.length){
            this.stack2.push(this.stack1.pop())
        }
        return this.stack2.pop()
    };
    
    /**
     * @return {number}
     */
    MyQueue.prototype.peek = function() {
        let item = this.pop()
        this.stack2.push(item)
        return item
    };
    
    /**
     * @return {boolean}
     */
    MyQueue.prototype.empty = function() {
        return !this.stack1.length && !this.stack2.length
    };
    
    

用队列实现栈

  • 其实这道题目就是用一个队列就够了。思路和上一道题差不多。

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

  • var MyStack = function() {
        this.queue1 = []
        this.queue2 = []
    };
    
    /** 
     * @param {number} x
     * @return {void}
     */
    MyStack.prototype.push = function(x) {
        this.queue1.push(x)
    };
    
    /**
     * @return {number}
     */
    MyStack.prototype.pop = function() {
        if(this.queue1.length == 0) [this.queue1,this.queue2] = [this.queue2,this.queue1]
        while(this.queue1.length>1){
            this.queue2.push(this.queue1.shift())
        }
        return this.queue1.shift()
    };
    
    /**
     * @return {number}
     */
    MyStack.prototype.top = function() {
        let item = this.pop()
        this.queue1.push(item)
        return item
    };
    
    /**
     * @return {boolean}
     */
    MyStack.prototype.empty = function() {
     return !this.queue1.length && !this.queue2.length;
    };
    
    

有效的括号

  • leetcode.cn/problems/va…

  • 栈的简单匹配。

  • var isValid = function(s) {
        let stack = []
        s = s.split('')
        let start = 0
        let len = s.length
        while(start<len){
            
            if(s[start]==('(')||s[start]==('[')||s[start]==('{')){
                stack.push(s[start])
                start++
                continue
            }
            console.log(stack)
            if(s[start]==')'){
                if(stack.pop()!=='(') return false
            }
            if(s[start]==']'){
                if(stack.pop()!=='[') return false
            }
            if(s[start]=='}'){
                if(stack.pop()!=='{') return false
            }
            start++
        }
        if(stack.length!=0) return false
        return true
    };
    // 简化版本
    var isValid = function(s) {
        const stack = [], 
            map = {
                "(":")",
                "{":"}",
                "[":"]"
            };
        for(const x of s) {
            if(x in map) {
                stack.push(x);
                continue;
            };
            if(map[stack.pop()] !== x) return false;
        }
        return !stack.length;
    };
    

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

  • leetcode.cn/problems/re…

  • var removeDuplicates = function(s) {
        let stack = []
        for(const item of s){
            if(!stack.length || stack[stack.length - 1] != item){
                stack.push(item)
                continue
            }
            stack.pop()
        }
        return stack.join("")
    };
    

逆波兰表达式求值

  • leetcode.cn/problems/ev…

  • 使用stack模拟后序表达式算法,在进行除法注意 要向0取整 ,math.trunc 如果你传递的参数x不是Number类型(即数字类型)的,那么它会被自动转换为Number类型 ,并且劫取整数部分。a/b|0,也是取整的方法

  • console.log(6/(-132)|0)
        let stack = []
        for(let i = 0 ; i < tokens.length ; i++){
            let item = tokens[i]
            console.log(stack)
            switch(item){
                case '+': 
                   stack.push(stack.pop()*1+stack.pop()*1)
                   break
                case '*': 
                   stack.push(stack.pop()*stack.pop())
                   break 
                case '/': 
                    let num1 = stack.pop()
                    let num2 = stack.pop()
                    stack.push(num2/num1|0)
                    break
                case '-': 
                    let num3 = stack.pop()
                    let num4 = stack.pop()
                    stack.push(num4-num3) 
                    break
                default :
                    stack.push(item)    
            }         
        }
        return stack.pop()
    };*/
    var evalRPN = function(tokens) {
        let stack = []
        const map = new Map([
            ["+", (a, b) => a * 1  + b * 1],
            ["-", (a, b) => b - a],
            ["*", (a, b) => b * a],
            ["/", (a, b) => b/a|0]
        ])
        console.log((6/-132)*10 + 17+5)
        console.log((4 + (13 / 5|0)))
        console.log(13/5)
        for(let item of tokens){
    
            if(map.has(item)){
                
                stack.push(map.get(item)(stack.pop(),stack.pop()))
            }else{
                stack.push(item)
            }
        }
        return stack.pop()
    }
    

滑动窗口最大值!

  • hard 题目 自己做出来了!!!!!leetcode.cn/problems/sl…

  • 首先肯定时想到用栈或者队列,懂得都懂,以及在队列中存值的下标 而不是值 ,这样用来比较滑动窗口的长度。队列中 保存从大到小的顺序,出现新最大值,就把前面的都排除掉,这样在窗口向下走的时候,可接续获取最大值!

  • // var maxSlidingWindow = function(nums, k) {
    //     if(k == 1) return nums
    //     let res = []
    //     let queue = [0]
    //     for(let i = 1 ; i < nums.length ; i++){
    //         while(queue.length && nums[i] > nums[queue[queue.length - 1]]){
    //             queue.pop()
    //         }
    //         queue.push(i)
    //         if(i >= k -1) {
    //             let index = 0
    //             while(queue[index]<=i-k){
    //                 queue.shift()
    //                 index++
    //             }
    //             res.push(nums[queue[0]])
    //         }
    //     }
    //     return res
    // };
    var maxSlidingWindow = function(nums, k) {
        let queue = []
        let res = []
        for(let i = 0 ; i <nums.length ; i++){
            while(nums[i]>nums[queue[queue.length-1]]&&queue.length){
                queue.pop()
            }
            queue.push(i)
            const done = i - k+1
            if(done>=0){
                if(queue[0]<done) queue.shift()
                res.push(nums[queue[0]])
            }
        }
        return res
    };
    

前k个高频元素

  • leetcode.cn/problems/to…

  • 取巧了说是

  • var topKFrequent = function(nums, k) {
        let map = new Map()
        for(const item of nums){
            map.set(item, (map.get(item)||0) + 1)
        }
        let arr = Array.from(map)
        return arr.sort((a,b) => b[1] - a[1]).slice(0,k).map(item => item[0])
    };