八、leetcode - 栈和队列(JS)

20. 有效的括号

给定一个只包括 ‘(’,’)’,’{’,’}’,’[’,’]’ 的字符串 s ,判断字符串是否有效。

有效字符串需满足:

左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。

输入: s = "()[]{}"
输出: true
[ '(' ] 
[] 
[ '[' ] 
[] 
[ '{' ] 
[]
/**
 * @param {string} s
 * @return {boolean}
 */
var isValid = function(s) {
    let map  = {'{':'}','(':')','[':']'};
    let stack = [];
    for(let i of s){
        if(map[i]){
            stack.push(i);
        }else{
            if(map[stack[stack.length - 1]] === i){
                stack.pop();
            }else{
                return false;
            }
        }
        console.info(stack);
    }
    return stack.length === 0;
};
155. 最小栈
输入:
["MinStack","push","push","push","getMin","pop","top","getMin"]
[[],[-2],[0],[-3],[],[],[],[]]

输出:
[null,null,null,null,-3,null,0,-2]

解释:
MinStack minStack = new MinStack();
minStack.push(-2);
minStack.push(0);
minStack.push(-3);
minStack.getMin();   --> 返回 -3.
minStack.pop();
minStack.top();      --> 返回 0.
minStack.getMin();   --> 返回 -2.
最小栈打印结果:
[ -2 ] 
[ -2, -2 ] 
[ -2, -2, -3 ]
/**
 * initialize your data structure here.
 */
var MinStack = function() {
    this.stack = [];
    this.minStack = [];
};

/** 
 * @param {number} val
 * @return {void}
 */
MinStack.prototype.push = function(val) {
    this.stack.push(val);
    let topOfMinStack = this.minStack[this.minStack.length - 1];
    if(this.minStack.length === 0 || val < topOfMinStack){
        this.minStack.push(val);
    } else {
        this.minStack.push(topOfMinStack);
    }
    console.info(this.minStack);
};

/**
 * @return {void}
 */
MinStack.prototype.pop = function() {
    this.stack.pop();
    this.minStack.pop();
};

/**
 * @return {number}
 */
MinStack.prototype.top = function() {
    return this.stack[this.stack.length - 1];
};

/**
 * @return {number}
 */
MinStack.prototype.getMin = function() {
    return this.minStack[this.minStack.length - 1];
};

/**
 * Your MinStack object will be instantiated and called as such:
 * var obj = new MinStack()
 * obj.push(val)
 * obj.pop()
 * var param_3 = obj.top()
 * var param_4 = obj.getMin()
 */
739. 每日温度

请根据每日 气温 列表 temperatures ,请计算在每一天需要等几天才会有更高的温度。如果气温在这之后都不会升高,请在该位置用 0 来代替。

输入: temperatures = [73,74,75,71,69,72,76,73]
输出: [1,1,4,2,1,1,0,0]
出栈     stack的值      stack       res
        [ 73 ]         [ 0 ]       [ 0, 0, 0, 0, 0, 0, 0, 0 ] 
1-0     [ 74 ]         [ 1 ]       [ 1, 0, 0, 0, 0, 0, 0, 0 ] 
2-1     [ 75 ]         [ 2 ]       [ 1, 1, 0, 0, 0, 0, 0, 0 ] 
        [ 75, 71 ]     [ 2, 3 ]    [ 1, 1, 0, 0, 0, 0, 0, 0 ] 
        [ 75, 71, 69 ] [ 2, 3, 4 ] [ 1, 1, 0, 0, 0, 0, 0, 0 ] 
5-4 5-3 [ 75, 72 ]     [ 2, 5 ]    [ 1, 1, 0, 2, 1, 0, 0, 0 ] 
6-5 6-2 [ 76 ]         [ 6 ]       [ 1, 1, 4, 2, 1, 1, 0, 0 ] 
        [ 76, 73 ]     [ 6, 7 ]    [ 1, 1, 4, 2, 1, 1, 0, 0 ]
/**
 * @param {number[]} temperatures
 * @return {number[]}
 */
var dailyTemperatures = function(temperatures) {
    let len = temperatures.length;
    let res = (new Array(len)).fill(0);
    let stack = [];
    for(let i = 0; i < len; i++) {
        while(stack.length && temperatures[i] > temperatures[stack[stack.length - 1]]) {
            let top = stack.pop();
            console.info(i + '-' + top);
            // 当前下标减去之前记录的下标
            res[top] = i - top;
        }
        stack.push(i);
        stack1.push(temperatures[i]);
        console.info(stack);
        console.info(res);
    }
    return res;
};
232. 用栈实现队列

用栈先进后出的方式来实现队列先进先出的效果

请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(push、pop、peek、empty):

实现 MyQueue 类:

void push(int x) 将元素 x 推到队列的末尾
int pop() 从队列的开头移除并返回元素
int peek() 返回队列开头的元素
boolean empty() 如果队列为空,返回 true ;否则,返回 false

说明:

你只能使用标准的栈操作 —— 也就是只有 push to top, peek/pop from top, size, 和 is empty 操作是合法的。
你所使用的语言也许不支持栈。你可以使用 list 或者 deque(双端队列)来模拟一个栈,只要是标准的栈操作即可。

输入:
["MyQueue", "push", "push", "peek", "pop", "empty"]
[[], [1], [2], [], [], []]
输出:
[null, null, null, 1, 1, false]

解释:
MyQueue myQueue = new MyQueue();
myQueue.push(1); // queue is: [1]
myQueue.push(2); // queue is: [1, 2] (leftmost is front of the queue)
myQueue.peek(); // return 1
myQueue.pop(); // return 1, queue is [2]
myQueue.empty(); // return false
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() {
    // 将入队栈中的数据导入到出队栈中
    if(!this.stack2.length) {
        while(this.stack1.length) {
            this.stack2.push(this.stack1.pop());
        }
    }
    return this.stack2.pop();
};

/**
 * @return {number}
 */
MyQueue.prototype.peek = function() {
    if(!this.stack2.length) {
        while(this.stack1.length) {
            this.stack2.push(this.stack1.pop());
        }
    }
    // 跟pop相比,只是不出队
    return this.stack2[this.stack2.length - 1];
};

/**
 * @return {boolean}
 */
MyQueue.prototype.empty = function() {
    // 入队栈和出队栈都为空时,队列为空
    return !this.stack1.length && !this.stack2.length;
};

/**
 * 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. 用队列实现栈

用队列先进先出的方式来实现栈先进后出的效果

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

请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(push、top、pop 和 empty)。

实现 MyStack 类:

void push(int x) 将元素 x 压入栈顶。
int pop() 移除并返回栈顶元素。
int top() 返回栈顶元素。
boolean empty() 如果栈是空的,返回 true ;否则,返回 false 。

注意:

你只能使用队列的基本操作 —— 也就是 push to back、peek/pop from front、size 和 is empty 这些操作。
你所使用的语言也许不支持队列。 你可以使用 list (列表)或者 deque(双端队列)来模拟一个队列 , 只要是标准的队列操作即可。

输入:
["MyStack", "push", "push", "top", "pop", "empty"]
[[], [1], [2], [], [], []]
输出:
[null, null, null, 2, 2, false]

解释:
MyStack myStack = new MyStack();
myStack.push(1);
myStack.push(2);
myStack.top(); // 返回 2
myStack.pop(); // 返回 2
myStack.empty(); // 返回 False
/**
 * Initialize your data structure here.
 */
var MyStack = function() {
    this.queue = [];
};

/**
 * Push element x onto stack. 
 * @param {number} x
 * @return {void}
 */
MyStack.prototype.push = function(x) {
    this.queue.push(x);
};

/**
 * Removes the element on top of the stack and returns that element.
 * @return {number}
 */
MyStack.prototype.pop = function() {
    let size = this.queue.length;
    while(size-- > 1) {
        this.queue.push(this.queue.shift());
    }
    return this.queue.shift();
};

/**
 * Get the top element.
 * @return {number}
 */
MyStack.prototype.top = function() {
    const x = this.pop();
    this.queue.push(x);
    return x;
};

/**
 * Returns whether the stack is empty.
 * @return {boolean}
 */
MyStack.prototype.empty = function() {
    return !this.queue.length;
};

/**
 * 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()
 */
239. 滑动窗口最大值

给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。

返回滑动窗口中的最大值。

输入:nums = [1,3,-1,-3,5,3,6,7], k = 3
输出:[3,3,5,5,6,7]
解释:
滑动窗口的位置                最大值
---------------               -----
[1  3  -1] -3  5  3  6  7       3
 1 [3  -1  -3] 5  3  6  7       3
 1  3 [-1  -3  5] 3  6  7       5
 1  3  -1 [-3  5  3] 6  7       5
 1  3  -1  -3 [5  3  6] 7       6
 1  3  -1  -3  5 [3  6  7]      7
窗口最开始从0扩张到k后,之后就一直维持k的大小,一步一步往后移,直到无法移动为止
i+1>=k   window      window对应的nums值
f        [ 0 ]       [ 1 ] 
f        [ 1 ]       [ 3 ] 
t        [ 1, 2 ]    [ 3, -1 ] 
t        [ 1, 2, 3 ] [ 3, -1, -3 ] 
t        [ 4 ]       [ 5 ] 
t        [ 4, 5 ]    [ 5, 3 ] 
t        [ 6 ]       [ 6 ] 
t        [ 7 ]       [ 7 ]
/**
 * @param {number[]} nums
 * @param {number} k
 * @return {number[]}
 */
var maxSlidingWindow = function(nums, k) {    
    let window = [];
    let res = [];
    for(let i = 0; i < nums.length; i++) {
        // 先把滑动窗口之外的踢出
        if(window[0] !== undefined && window[0] <= i - k) window.shift();
        // 保证队首是最大的
        while(nums[window[window.length - 1]] <= nums[i])  window.pop();
        window.push(i);
        if(i + 1 >= k) res.push(nums[window[0]]);
        console.info(window);
    }
    return res;
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值