栈的实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
| function Stack() { this.items = []
Stack.prototype.push = function (element) { this.items.push(element) }
Stack.prototype.pop = function () { return this.items.pop() }
Stack.prototype.peek = function () { return this.items[this.items.length - 1] }
Stack.prototype.isEmpty = function () { return this.items.length == 0 }
Stack.prototype.clear = function () { this.items = [] }
Stack.prototype.size = function () { return this.items.length }
Stack.prototype.toString = function () { return this.items.join(" ") }
}
var stack = new Stack() stack.push(1) stack.push(2)
stack.size()
|
栈的应用
十进制转二进制
使用栈来存储循环除法的值,然后循环从栈顶取值就是该值的二进制。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| function dec2bin(decNumber) { var stack = new Stack() var remainder
while (decNumber > 0) { remainder = decNumber % 2 stack.push(remainder) decNumber = Math.floor(decNumber / 2) }
console.log(stack.toString());
var binaryString = '' while(stack.size() > 0) { binaryString += stack.pop() }
return binaryString }
var stack = new Stack() stack.push(1) stack.push(2)
var test = dec2bin(235) console.log(test);
|
(*)用两个栈实现队列
地址:232. 用栈实现队列 - 力扣(LeetCode)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| var MyQueue = function() { this.stackIn = [] this.stackOut = [] };
MyQueue.prototype.push = function(x) { this.stackIn.push(x) };
MyQueue.prototype.pop = function() { const length = this.stackOut.length if(length) { return this.stackOut.pop() } while(this.stackIn.length) { this.stackOut.push(this.stackIn.pop()) } return this.stackOut.pop() };
MyQueue.prototype.peek = function() { const x = this.pop(); this.stackOut.push(x); return x; };
MyQueue.prototype.empty = function() { return !this.stackIn.length && !this.stackOut.length };
|
有效的括号
地址:20. 有效的括号 - 力扣(LeetCode)
题解参考代码随想录。
地址:代码随想录 (programmercarl.com)
由于栈结构的特殊性,非常适合做对称匹配类的题目。
首先要弄清楚,字符串里的括号不匹配有几种情况。
一些同学,在面试中看到这种题目上来就开始写代码,然后就越写越乱。
建议要写代码之前要分析好有哪几种不匹配的情况,如果不动手之前分析好,写出的代码也会有很多问题。
先来分析一下 这里有三种不匹配的情况,
- 第一种情况,字符串里左方向的括号多余了 ,所以不匹配。

- 第二种情况,括号没有多余,但是 括号的类型没有匹配上。

- 第三种情况,字符串里右方向的括号多余了,所以不匹配。

我们的代码只要覆盖了这三种不匹配的情况,就不会出问题,可以看出 动手之前分析好题目的重要性。
动画如下:

第一种情况:已经遍历完了字符串,但是栈不为空,说明有相应的左括号没有右括号来匹配,所以return false
第二种情况:遍历字符串匹配的过程中,发现栈里没有要匹配的字符。所以return false
第三种情况:遍历字符串匹配的过程中,栈已经为空了,没有匹配的字符了,说明右括号没有找到对应的左括号return false
那么什么时候说明左括号和右括号全都匹配了呢,就是字符串遍历完之后,栈是空的,就说明全都匹配了。
分析完之后,代码其实就比较好写了。
JS代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
|
var isValid = function(s) { let stack = [] let map = new Map([ ['(', ')'], ['{', '}'], ['[', ']'] ]) for(let i = 0; i < s.length; i++) { if(map.has(s[i])) { stack.push(map.get(s[i])) } else { let x = stack.pop(); if(x !== s[i]) { return false } } } return stack.length === 0 };
|
删除字符串中的所有相邻重复项
地址:1047. 删除字符串中的所有相邻重复项 - 力扣(LeetCode)
这题的思路和上面的匹配括号一致,掌握上一题,这一题就很简单。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
|
var removeDuplicates = function(s) { let stack = [] for(let i = 0; i < s.length; i++) { let x = stack[stack.length - 1]; if(x == s[i]) { stack.pop() } else { stack.push(s[i]) } } return stack.join('') };
|
逆波兰表达式求值
地址:150. 逆波兰表达式求值 - 力扣(LeetCode)
思路:看个图

代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
|
var evalRPN = function(tokens) { let set = new Set(['*', '/', '+', '-']) let stack = [] for(let i = 0; i < tokens.length; i++) { if(set.has(tokens[i])) { let y = stack.pop() let x = stack.pop() let result = 0 switch(tokens[i]) { case '*': result = x * y; break; case '/': if(x / y > 0) { result = Math.floor(x / y); } else { result = Math.ceil(x / y) } break; case '+': result = x + y; break; case '-': result = x - y; break; } stack.push(result) } else { stack.push(+tokens[i]) } } return stack.pop() };
|
队列的实现
普通队列
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| function Queue() { this.items = []
Queue.prototype.enqueue = function (element) { this.items.push(element) }
Queue.prototype.dequeue = function () { return this.items.shift() }
Queue.prototype.front = function () { return this.items[0] }
Queue.prototype.isEmpty = function () { return this.items.length == 0 }
Queue.prototype.size = function () { return this.items.length } }
|
优先队列
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
| function PriorityQueue() { this.items = []
function QueueElement(element,priority) { this.element = element this.priority = priority }
PriorityQueue.prototype.enqueue = function (element,priority) { var queueElement = new QueueElement(element,priority)
if (this.isEmpty()) { this.items.push(queueElement) } else { var added = false for(var i = 0;i < this.items.length;i++) { if (this.items[i].priority > queueElement.priority) { this.items.splice(i,0,queueElement) added = true break } }
if (!added) { this.items.push(queueElement) } } }
PriorityQueue.prototype.dequeue = function () { return this.items.shift() }
PriorityQueue.prototype.front = function () { return this.items[0] }
PriorityQueue.prototype.isEmpty = function () { return this.items.length == 0 }
PriorityQueue.prototype.size = function () { return this.items.length } }
|
队列的应用
约瑟夫环
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
|
var queue = new Queue() queue.enqueue('lily') queue.enqueue('lucy') queue.enqueue('tom') queue.enqueue('lilei') queue.enqueue('why')
var count = 0; while (queue.size() > 1) { count++; if (count == 3) { queue.dequeue(); count = 0; } else { var temp = queue.dequeue(); queue.enqueue(temp); }
} console.log(queue.front());
|
(*)用队列实现栈
地址:225. 用队列实现栈 - 力扣(LeetCode)
思路:如图

代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| var MyStack = function() { this.queueIn = [] this.queueOut = [] };
MyStack.prototype.push = function(x) { this.queueIn.push(x) };
MyStack.prototype.pop = function() { let temp = null this.queueOut = [] while(this.queueIn.length - 1) { temp = this.queueIn.shift(); this.queueOut.push(temp) } temp = this.queueIn.shift() this.queueIn = [...this.queueOut] return temp };
MyStack.prototype.top = function() { let temp = null this.queueOut = [] while (this.queueIn.length) { temp = this.queueIn.shift(); this.queueOut.push(temp); } this.queueIn = [...this.queueOut]; return temp; };
MyStack.prototype.empty = function() { return this.queueIn.length === 0 };
|
(*)滑动窗口最大值
地址:239. 滑动窗口最大值 - 力扣(LeetCode)
这题要使用单调队列,设计的还是挺巧妙的,也不难。
题解:代码随想录 (programmercarl.com)

代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
|
var maxSlidingWindow = function(nums, k) { class MonoQueue { queue; constructor() { this.queue = [] } enqueue(value) { let temp = this.queue[this.queue.length - 1] while(value > temp && temp != undefined) { this.queue.pop() temp = this.queue[this.queue.length - 1] } this.queue.push(value) } dequeue(value) { if(value === this.front()) { this.queue.shift() } } front() { return this.queue[0] } }
let queue = new MonoQueue() let result = [] for(let i = 0; i < k; i++) { queue.enqueue(nums[i]) } result.push(queue.front()) for(let i = k; i < nums.length; i++) { queue.enqueue(nums[i]) queue.dequeue(nums[i - k]) result.push(queue.front()) } return result };
|
前K个高频元素(TODO)
地址:代码随想录 (programmercarl.com)
这题要用到堆,大顶堆,小顶堆还没复习到,先暂时跳过