本文首发于 我的 Github
栈
栈遵循 后进先出 的原则。
/**
* 栈
* 后进先出
*/
class Stack {
constructor() {
this.items = [];
}
// 添加元素
push(value) {
this.items.push(value);
}
// 返回栈顶的元素
peek() {
return this.items[this.items.length - 1];
}
// 移出栈顶的元素
pop() {
return this.items.pop();
}
/**
* 判断栈是否为空
*/
isEmpty() {
return this.items.length <= 0;
}
}
队列
队列遵循 先进先出 的原则。
/**
* 队列
* 先进先出
*/
class Queue {
constructor() {
this.items = [];
}
/**
* 添加元素
*/
enqueue(value) {
this.items.push(value);
}
/**
* 移出队列的第一个元素
*/
dequeue() {
return this.items.shift();
}
}
常见题目
1. 有效的括号
问题描述
给定一个只包括 '(',')','{','}','[',']'的字符串,判断字符串是否有效。
解题思路
使用 栈 来解决。
- 遍历字符串,如果是左括号便压入栈中。
- 如果遇到右括号,分类谈论:
- 如果当前栈为空,返回
false - 取出栈顶元素,如果与之匹配继续循环,否则返回
false
- 如果当前栈为空,返回
/**
* 给定一个只包括 '(',')','{','}','[',']' 的字符串,判断字符串是否有效。
* @param {*} str
*/
function isValidStr(str) {
let arr = str.split("");
let stack = new Stack();
function isMatchStr(a, b) {
return (
(a === "(" && b === ")") ||
(a === "[" && b === "]") ||
(a === "{" && b === "}")
);
}
while (arr.length) {
let char = arr.shift();
if (char === "(" || char === "[" || char === "{") {
stack.push(char);
} else {
if (stack.isEmpty()) {
return false;
} else if (isMatchStr(stack.pop(), char)) {
continue;
} else {
return false;
}
}
}
return true;
}
2. 用两个栈实现队列
问题描述
用两个栈来实现一个队列,完成队列的 enqueue 和 dequeue 操作。
解题思路
in 栈用于处理 入列 操作,out 栈用于处理 出列 操作。
- 入列的值直接压入
in栈 - 出列时,将
in栈的元素出栈压入到out栈,然后返回out栈栈顶的元素(这样便保持了队列先进先出的原则)。
class TwoStackQueue {
constructor() {
this.inStack = new Stack();
this.outStack = new Stack();
}
enqueue(value) {
this.inStack.push(value);
}
dequeue() {
while (!this.inStack.isEmpty()) {
this.outStack.push(this.inStack.pop());
}
return this.outStack.pop();
}
}
3. 栈的压入、弹出序列
问题描述
输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列 1,2,3,4,5 是某栈的压入顺序,序列 4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。(注意:这两个序列的长度是相等的)
解题思路
初始化一个辅助栈,遍历压入顺序,执行入栈操作,入栈的同时,如果辅助栈非空,同时弹出序列的当前值与辅助栈栈顶元素相同,则辅助栈出栈。最后判断辅助是否为空,为空这是正确的顺序,否则不是。例如:
入栈:1, 2, 3, 4, 5
出栈:4, 5, 3, 2, 1
首先,1 入栈,此时栈顶元素 1 != 4,继续入栈;
2 != 4,入栈;
3 != 4 入栈;
4 == 4,入栈后出栈(这时候栈内元素为 1, 2, 3);
3 != 5,入栈(这时候栈内元素为 1, 2, 3, 5),5 == 5 出栈,3 == 3 出栈...
最后栈为空,顺序匹配。
function isPopOrder(pushOrder, popOrder) {
let stack = new Stack();
let popIndex = 0;
for (let pushIndex = 0; pushIndex < pushOrder.length; pushIndex++) {
stack.push(pushOrder[pushIndex]);
while (!stack.isEmpty() && stack.peek() === popOrder[popIndex]) {
stack.pop();
popIndex++;
}
}
return stack.isEmpty();
}