栈数据结构
栈的定义
数据结构中的栈是一种特殊的线性表, 遵循后进先出原则(LIFO: Last In First Out), 只能在数据的一端进行入栈(push)和出栈(pop)的操作, 该端称为栈顶。栈顶用远是最新的元素。
栈的实现
栈常用方法如下:
push 添加一个(或几个)新元素到栈顶
pop 溢出栈顶元素,同时返回被移除的元素
peek 返回栈顶元素,不对栈做修改
isEmpty 栈内无元素返回true,否则返回false
size 返回栈内元素个数
clear 清空栈
// @ts-check
export default class Stack {
constructor() {
this.count = 0;
this.items = {};
}
push(element) {
this.items[this.count] = element;
this.count++;
}
pop() {
if (this.isEmpty()) {
return undefined;
}
this.count--;
const result = this.items[this.count];
delete this.items[this.count];
return result;
}
peek() {
if (this.isEmpty()) {
return undefined;
}
return this.items[this.count - 1];
}
isEmpty() {
return this.count === 0;
}
size() {
return this.count;
}
clear() {
/* while (!this.isEmpty()) {
this.pop();
} */
this.items = {};
this.count = 0;
}
toString() {
if (this.isEmpty()) {
return '';
}
let objString = `${this.items[0]}`;
for (let i = 1; i < this.count; i++) {
objString = `${objString},${this.items[i]}`;
}
return objString;
}
}
栈的应用
有效的括号
给定一个只包括 '(',')','{','}','[',']' 的字符串,判断字符串是否有效。
输入: "()"
输出: true
输入: "()[]{}"
输出: true
输入: "(]"
输出: false
来源: leetcode-cn.com/problems/va…
var isValid = function(s) {
let stack = [];
for (let i = 0; i < s.length; i++) {
let ch = s[i];
if(ch == '(' || ch == '{' || ch == '[' ) {
stack.push(ch)
}
if(!stack.length) return false;
if(ch === ')' && stack.pop() !== '(') return false;
if(ch === '}' && stack.pop() !== '{') return false;
if(ch === ']' && stack.pop() !== '[') return false;
}
return stack.length === 0;
};
删除字符串中的所有相邻重复项
给出由小写字母组成的字符串 S,重复项删除操作会选择两个相邻且相同的字母,并删除它们。 在 S 上反复执行重复项删除操作,直到无法继续删除。 在完成所有重复项删除操作后返回最终的字符串。答案保证唯一。
输入:"abbaca"
输出:"ca"
解释:
例如,在 "abbaca" 中,我们可以删除 "bb" 由于两字母相邻且相同,这是此时唯一可以执行删除
操作的重复项。之后我们得到字符串 "aaca",其中又只有 "aa" 可以执行重复项删除操作,所以最
后的字符串为 "ca"。
输入:"abbbaca"
输出:"abaca"
来源: leetcode-cn.com/problems/re…
var removeDuplicates = function(S) {
let stack = [];
for (let c of S) {
let prev = stack.pop();
if(c !== prev) {
stack.push(prev);
stack.push(c)
}
}
return stack.join('');
};
删除字符串中的所有相邻重复项 II
给你一个字符串 s,「k 倍重复项删除操作」将会从 s 中选择 k 个相邻且相等的字母,并删除它们,使被删去的字符串的左侧和右侧连在一起。 你需要对 s 重复进行无限次这样的删除操作,直到无法继续为止。 在执行完所有删除操作后,返回最终得到的字符串。 本题答案保证唯一。
输入:s = "deeedbbcccbdaa", k = 3
输出:"aa"
解释:
先删除 "eee" 和 "ccc",得到 "ddbbbdaa"
再删除 "bbb",得到 "dddaa"
最后删除 "ddd",得到 "aa"
输入:s = "pbbcggttciiippooaais", k = 2
输出:"ps"
来源: leetcode-cn.com/problems/re…
var removeDuplicates = function(s, k) {
let stack = [];
for (let c of s) {
let prev = stack.pop();
if(!prev || c !== prev[0]) {
stack.push(prev);
stack.push(c)
} else if(prev.length < k - 1) {
stack.push(prev + c)
}
}
return stack.join('');
};
删除字符串中出现次数大于等于k次的相邻字符
输入:s = "abbbaca", k = 2
输出:"ca"
var removeDuplicates = function(s, k) {
let stack = [];
for (let i = 0; i < s.length; i++) {
let prev = stack.pop();
if(!prev || prev[0] != s[i]) {
stack.push(prev);
stack.push(s[i]);
} else if(prev.length < k - 1 || prev[0] === s[i + 1]) {
stack.push(prev + s[i])
}
}
return stack.join('');
}
下一个更大元素 II
给定一个循环数组(最后一个元素的下一个元素是数组的第一个元素),输出每个元素的下一个更大元素。数字 x 的下一个更大的元素是按数组遍历顺序,这个数字之后的第一个比它更大的数,这意味着你应该循环地搜索它的下一个更大的数。如果不存在,则输出 -1。
输入: [1,2,1]
输出: [2,-1,2]
解释: 第一个 1 的下一个更大的数是 2;
数字 2 找不到下一个更大的数;
第二个 1 的下一个最大的数需要循环搜索,结果也是 2。
来源: leetcode-cn.com/problems/ne…
// 1.将数组中所有元素全部置为-1
// 2.遍历两次,相当于循环遍历
// 3.第一遍遍历,入栈索引i
// 4.只要后面元素比栈顶索引对应的元素大,索引出栈,更改res[sta.pop()]的数值
// 5.最后栈里面剩余的索引对应的数组值,都为默认的-1(因为后面未找到比它大的值)
var nextGreaterElements = function(nums) {
let n = nums.length;
let res = new Array(n).fill(-1);
let stack = [];
for (let i = 0; i < n*2; i++) {
let num = nums[i%n];
while(stack.length !== 0 && num > nums[stack[stack.length - 1]]) {
res[stack.pop()] = num;
}
if(i < n) {
stack.push(i)
}
}
return res;
};
字符串解码
给定一个经过编码的字符串,返回它解码后的字符串。 编码规则为: k[encoded_string],表示其中方括号内部的 encoded_string 正好重复 k 次。注意 k 保证为正整数。
输入:s = "3[a]2[bc]"
输出:"aaabcbc"
输入:s = "3[a2[c]]"
输出:"accaccacc"
输入:s = "abc3[cd]xyz"
输出:"abccdcdcdxyz"
来源: leetcode-cn.com/problems/de…
var decodeString = function(s) {
let stack_num = [], stack_char = [], res = '', num_str = '';
for (let item of s) {
if(item >= '0' && item <= '9') {
num_str += item;
} else if(item === '[') {
stack_char.push(res);
stack_num.push(num_str);
res = '';
num_str = '';
} else if(item === ']') {
let count = Number(stack_num.pop());
res = stack_char.pop() + res.repeat(count)
} else {
res += item;
}
}
return res;
};
删除最外层的括号
输入:"(()())(())"
输出:"()()()"
解释:
输入字符串为 "(()())(())",原语化分解得到 "(()())" + "(())",
删除每个部分中的最外层括号后得到 "()()" + "()" = "()()()"。
输入:"(()())(())(()(()))"
输出:"()()()()(())"
解释:
输入字符串为 "(()())(())(()(()))",原语化分解得到 "(()())" + "(())" + "(()(()))",
删除每个部分中的最外层括号后得到 "()()" + "()" + "()(())" = "()()()()(())"。
输入:"()()"
输出:""
解释:
输入字符串为 "()()",原语化分解得到 "()" + "()",
删除每个部分中的最外层括号后得到 "" + "" = ""。
来源: leetcode-cn.com/problems/re…
var removeOuterParentheses = function(S) {
let res = '', stack = [];
for (let i = 0; i < S.length; i++) {
if(S[i] === ')') {
stack.pop();
}
if(stack.length > 0) {
res += S[i]
}
if(S[i] === '(') {
stack.push(S[i])
}
}
return res;
};
移掉K位数字
给定一个以字符串表示的非负整数num,移除这个数中的k位数字,使得剩下的数字最小。
输入: num = "1432219", k = 3
输出: "1219"
解释: 移除掉三个数字 4, 3, 和 2 形成一个新的最小的数字 1219。输入: num = "10200", k = 1
输出: "200"
解释: 移掉首位的 1 剩下的数字为 200\. 注意输出不能有任何前导零。输入: num = "10", k = 2
输出: "0"
解释: 从原数字移除所有的数字,剩余为空就是0。
来源: leetcode-cn.com/problems/re…
var removeKdigits = function(num, k) {
let stack = [];
for (let i = 0; i < num.length; i++) {
let tmp = num[i];
while(stack.length > 0 && k > 0 && tmp < stack[stack.length - 1]) {
stack.pop();
k--;
}
stack.push(tmp);
}
while(k > 0) {
stack.pop();
k--;
}
while(stack.length > 0 && stack[0] === '0') {
stack.shift()
}
return stack.length > 0 ? stack.join('') : '0';
};
比较含退格的字符串
给定 S 和 T 两个字符串,当它们分别被输入到空白的文本编辑器后,判断二者是否相等,并返回结果。 # 代表退格字符。
输入:S = "ab#c", T = "ad#c"
输出:true
解释:S 和 T 都会变成 “ac”。
输入:S = "ab##", T = "c#d#"
输出:true
解释:S 和 T 都会变成 “”。
输入:S = "a#c", T = "b"
输出:false
解释:S 会变成 “c”,但 T 仍然是 “b”。
来源: leetcode-cn.com/problems/ba…
var backspaceCompare = function(S, T) {
let stackS = [], stackT = [];
for (let i = 0 ; i < S.length; i++) {
if(S[i] === '#') {
stackS.pop();
} else {
stackS.push(S[i]);
}
}
for (let j = 0 ; j < T.length; j++) {
if(T[j] === '#') {
stackT.pop();
} else {
stackT.push(T[j]);
}
}
return stackS.join('') === stackT.join('');
};
棒球比赛
你现在是棒球比赛记录员。 给定一个字符串列表,每个字符串可以是以下四种类型之一:
- 1.整数(一轮的得分):直接表示您在本轮中获得的积分数。
- 2. "+"(一轮的得分):表示本轮获得的得分是前两轮有效 回合得分的总和。
- 3. "D"(一轮的得分):表示本轮获得的得分是前一轮有效 回合得分的两倍。
- 4. "C"(一个操作,这不是一个回合的分数):表示您获得的最后一个有效 回合的分数是无效的,应该被移除。
每一轮的操作都是永久性的,可能会对前一轮和后一轮产生影响。 你需要返回你在所有回合中得分的总和。
输入: ["5","2","C","D","+"]
输出: 30
解释:
第1轮:你可以得到5分。总和是:5。
第2轮:你可以得到2分。总和是:7。
操作1:第2轮的数据无效。总和是:5。
第3轮:你可以得到10分(第2轮的数据已被删除)。总数是:15。
第4轮:你可以得到5 + 10 = 15分。总数是:30。
输入: ["5","-2","4","C","D","9","+","+"]
输出: 27
解释:
第1轮:你可以得到5分。总和是:5。
第2轮:你可以得到-2分。总数是:3。
第3轮:你可以得到4分。总和是:7。
操作1:第3轮的数据无效。总数是:3。
第4轮:你可以得到-4分(第三轮的数据已被删除)。总和是:-1。
第5轮:你可以得到9分。总数是:8。
第6轮:你可以得到-4 + 9 = 5分。总数是13。
第7轮:你可以得到9 + 5 = 14分。总数是27。
来源: leetcode-cn.com/problems/ba…
var calPoints = function(ops) {
let stack = [], sum = 0;
for (let i = 0; i < ops.length; i++) {
let tmp, item = ops[i];
if(item === '+') {
tmp = stack[stack.length - 1] + stack[stack.length - 2];
stack.push(tmp);
sum += tmp;
} else if(item === 'D') {
tmp = stack[stack.length - 1] * 2;
stack.push(tmp);
sum += tmp;
} else if(item === 'C') {
sum -= stack.pop();
} else {
stack.push(Number(item));
sum += Number(item);
}
}
return sum;
};
简化路径
以 Unix 风格给出一个文件的绝对路径,你需要简化它。或者换句话说,将其转换为规范路径。
输入:"/home/"
输出:"/home"
解释:注意,最后一个目录名后面没有斜杠。
来源: leetcode-cn.com/problems/si…
//将path以'/'分割成数组,如 /a/./b/../../c/分割成[ '', 'a', '.', 'b', '..', '..', 'c', '' ]。
//新建一个栈stack为当前的路径,遍历path分割后的数组元素:
//遇到正常的字母时,推入 stack 中
//遇到 .. 时,stack 弹出最近一个路径
//遇到 . 或者为空时,不修改当前 stack。
//最后返回 '/' + stack.join('/') 为新的路径
var simplifyPath = function(path) {
let stack = [], arr = path.split('/');
for (let i = 0; i < arr.length; i++) {
if(arr[i] === '.' || arr[i] === '') {
continue;
} else if(arr[i] === '..') {
stack.pop();
} else {
stack.push(arr[i])
}
}
return '/' + stack.join('/');
};
去除重复字母
给你一个字符串 s ,请你去除字符串中重复的字母,使得每个字母只出现一次。需保证 返回结果的字典序最小(要求不能打乱其他字符的相对位置)。
输入:s = "bcabc"
输出:"abc"
来源: leetcode-cn.com/problems/re…
var removeDuplicateLetters = function(s) {
let stack = [];
for (let i = 0; i < s.length; i++) {
if(stack.indexOf(s[i]) > -1) continue;
while(stack.length > 0 && stack[stack.length - 1] > s[i] && s.indexOf(stack[stack.length - 1], i) > i) {
stack.pop()
}
stack.push(s[i])
}
return stack.join('');
};
逆波兰表达式求值
根据 逆波兰表示法,求表达式的值。有效的运算符包括 +, -, *, / 。每个运算对象可以是整数,也可以是另一个逆波兰表达式。
输入: ["2", "1", "+", "3", "*"]
输出: 9
解释: 该算式转化为常见的中缀算术表达式为:((2 + 1) * 3) = 9
来源: leetcode-cn.com/problems/ev…
var evalRPN = function(tokens) {
const stack = [];
for (let index = 0; index < tokens.length; index++) {
const token = tokens[index];
if(!Number.isNaN(Number(token))) {
stack.push(token);
} else {
const a = Number(stack.pop());
const b = Number(stack.pop());
if(token === '*') {
stack.push(b * a);
} else if(token === '/') {
stack.push(b / a >> 0);
} else if(token === '+') {
stack.push(b + a);
} else if(token === '-') {
stack.push(b -a);
}
}
}
return stack.pop();
};
栈的压入、弹出序列
输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如,序列 {1,2,3,4,5} 是某栈的压栈序列,序列 {4,5,3,2,1} 是该压栈序列对应的一个弹出序列,但 {4,3,5,1,2} 就不可能是该压栈序列的弹出序列。
输入:pushed = [1,2,3,4,5], popped = [4,5,3,2,1]
输出:true
解释:我们可以按以下顺序执行:
push(1), push(2), push(3), push(4), pop() -> 4,
push(5), pop() -> 5, pop() -> 3, pop() -> 2, pop() -> 1
输入:pushed = [1,2,3,4,5], popped = [4,3,5,1,2]
输出:false
解释:1 不能在 2 之前弹出。
来源: leetcode-cn.com/problems/zh…
var validateStackSequences = function(pushed, popped) {
let stack = [];
let j = 0;
for (let i = 0; i < pushed.length; i++) {
stack.push(pushed[i]);
while(stack.length !== 0 && stack[stack.length - 1] === popped[j]) {
stack.pop();
j++;
}
}
return stack.length === 0;
};
检查替换后的词是否有效
输入:"aabcbc"
输出:true
解释:
从有效字符串 "abc" 开始。
然后我们可以在 "a" 和 "bc" 之间插入另一个 "abc",产生 "a" + "abc" + "bc",即 "aabcbc"。
来源: leetcode-cn.com/problems/ch…
// 当遇到字符a时,直接入栈
// 当遇到字符b时,检查栈顶是否为字符a ,如果是将b入栈,如果不是返回false;
// 当遇到字符c时,检查栈顶是否为字符b,如果是将c入栈,(再将栈顶的cba弹出)如果不是返回false
// 最后判断栈是否为空即可
var isValid = function(S) {
let stack = [];
for (let item of S) {
if(item === 'b' && (stack.length === 0 || stack[stack.length - 1] !== 'a')) {
return false;
}
if(item === 'c' && (stack.length === 0 || stack[stack.length - 1] !== 'b')) {
return false;
}
stack.push(item);
if(item === 'c') {
stack.pop();
stack.pop();
stack.pop()
}
}
return stack.length === 0;
};
每日温度
请根据每日 气温 列表,重新生成一个列表。对应位置的输出为:要想观测到更高的气温,至少需要等待的天数。如果气温在这之后都不会升高,请在该位置用 0 来代替。 例如,给定一个列表 temperatures = [73, 74, 75, 71, 69, 72, 76, 73],你的输出应该是 [1, 1, 4, 2, 1, 1, 0, 0]。
来源: leetcode-cn.com/problems/da…
var dailyTemperatures = function(T) {
let res = new Array(T.length).fill(0);
let stack = [];
for (let i = 0; i < T.length; i++) {
while(stack.length > 0 && T[i] > T[stack[stack.length - 1]]) {
let idx = stack.pop();
res[idx] = i - idx;
}
stack.push(i)
}
return res;
};
柱状图中最大的矩形
给定n个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。求在该柱状图中,能够勾勒出来的矩形的最大面积。
输入: [2,1,5,6,2,3]
输出: 10
来源: leetcode-cn.com/problems/la…
var largestRectangleArea = function(heights) {
let stack = [], maxArea = 0;
heights = [0, ...heights, 0];
for (let i = 0; i < heights.length; i++) {
while(heights[i] < heights[stack[stack.length - 1]]) {
let topStackIdx = stack.pop();
maxArea = Math.max(
maxArea,
heights[topStackIdx] * (i - stack[stack.length - 1] - 1)
)
}
stack.push(i)
}
return maxArea;
};
最大矩形
给定一个仅包含 0 和 1 的二维二进制矩阵,找出只包含 1 的最大矩形,并返回其面积。
输入:
[ ["1","0","1","0","0"],
["1","0","1","1","1"],
["1","1","1","1","1"],
["1","0","0","1","0"]
]
输出: 6
来源: leetcode-cn.com/problems/ma…
var maximalRectangle = function(matrix) {
if(!matrix.length || !matrix[0].length) return 0;
let m = matrix.length, n = matrix[0].length, ans = 0;
let heghts = new Array(n + 2).fill(0);
for (let i = 0; i < m; i++) {
for (let j = 0; j < n; j++) {
if(matrix[i][j] === '1') heghts[j + 1]++;
else heghts[j + 1] = 0;
}
let stack = [], max = 0;
for (let j = 0; j < heghts.length; j++) {
while(stack.length && heghts[j] < heghts[stack[stack.length - 1]]) {
let top = stack.pop();
max = Math.max(
max,
heghts[top] * (j - stack[stack.length - 1] - 1)
);
}
stack.push(j)
}
ans = Math.max(ans, max);
}
return ans;
};
链表中的下一个更大节点
输入:[2,1,5]
输出:[5,5,0]
来源: leetcode-cn.com/problems/ne…
var nextLargerNodes = function(head) {
let arr = [], valArr = [], stack = [];
let i = 0, value;
while(head) {
value = head.val;
valArr[i] = value;
while(stack.length > 0 && value > valArr[stack[stack.length - 1]]) {
arr[stack.pop()] = value;
}
stack.push(i);
i++;
head = head.next;
}
let res = new Array(i).fill(0);
for (let j = 0; j < i; j++) {
if(arr[j]) {
res[j] = arr[j]
}
}
return res;
};
不同字符的最小子序列
返回字符串 text 中按字典序排列最小的子序列,该子序列包含 text 中所有不同字符一次。
输入:"cdadabcc"
输出:"adbc"输入:"abcd"
输出:"abcd"
来源: leetcode-cn.com/problems/sm…
var smallestSubsequence = function(text) {
let len = text.length;
let stack = [];
for (let i = 0; i < len; i++) {
let char = text.charAt(i);
if(stack.indexOf(char) != -1) {
continue
}
while(stack.length > 0 && char < stack[stack.length - 1] && text.indexOf(stack[stack.length - 1], i) != -1) {
stack.pop()
}
stack.push(char)
}
let res = "";
for (let item of stack) {
res += item
}
return res;
};
队列数据结构
定义
队列是遵循先进先出(FIFO, First In First Out)原则的一组有序的项。队列在尾部添加新元素,并从顶部移除元素。最新添加的元素必须排在队列的末尾.
队列的实现
队列常用方法:
enqueue 向队列尾部添加一个(或多个)新的项
dequeue 移除队列的第一(即排在队列最前面的)项,并返回被移除的元素
head 返回队列第一个元素,队列不做任何变动
tail 返回队列最后一个元素,队列不做任何变动
isEmpty 队列内无元素返回true,否则返回false
size 返回队列内元素个数
clear 清空队列
export default class Queue {
constructor() {
this.count = 0;
this.lowestCount = 0;
this.items = {};
}
enqueue(element) {
this.items[this.count] = element;
this.count++;
}
dequeue() {
if (this.isEmpty()) {
return undefined;
}
const result = this.items[this.lowestCount];
delete this.items[this.lowestCount];
this.lowestCount++;
return result;
}
peek() {
if (this.isEmpty()) {
return undefined;
}
return this.items[this.lowestCount];
}
isEmpty() {
return this.size() === 0;
}
clear() {
this.items = {};
this.count = 0;
this.lowestCount = 0;
}
size() {
return this.count - this.lowestCount;
}
toString() {
if (this.isEmpty()) {
return '';
}
let objString = `${this.items[this.lowestCount]}`;
for (let i = this.lowestCount + 1; i < this.count; i++) {
objString = `${objString},${this.items[i]}`;
}
return objString;
}
}
DFS和BFS与栈和队列的关系
DFS采用递归的形式, 用到了栈结构, 先进先出。BFS选取状态用队列的形式, 先进先出。
队列的应用
根据身高重建队列
假设有打乱顺序的一群人站成一个队列。 每个人由一个整数对(h, k)表示,其中h是这个人的身高,k是排在这个人前面且身高大于或等于h的人数。 编写一个算法来重建这个队列。
输入:
[[7,0], [4,4], [7,1], [5,0], [6,1], [5,2]]
输出:
[[5,0], [7,0], [5,2], [6,1], [4,4], [7,1]]
来源: leetcode-cn.com/problems/qu…
var reconstructQueue = function(people) {
let ans = [];
people.sort((a,b) => {
return a[0] === b[0] ? a[1] - b[1] : b[0] - a[0];
});
for(let i = 0 ; i < people.length; i++) {
ans.splice(people[i][1],0,people[i]);
}
return ans;
};
最近的请求次数
写一个 RecentCounter 类来计算特定时间范围内最近的请求。 请你实现 RecentCounter 类: RecentCounter() 初始化计数器,请求数为 0 。 int ping(int t) 在时间 t 添加一个新请求,其中 t 表示以毫秒为单位的某个时间,并返回过去 3000 毫秒内发生的所有请求数(包括新请求)。确切地说,返回在 [t-3000, t] 内发生的请求数。 保证每次对 ping 的调用都使用比之前更大的 t 值。
输入:
["RecentCounter", "ping", "ping", "ping", "ping"]
[[], [1], [100], [3001], [3002]]
输出:
[null, 1, 2, 3, 3]
来源: leetcode-cn.com/problems/nu…
var RecentCounter = function() {
this.queue = [];
};
/**
* @param {number} t
* @return {number}
*/
RecentCounter.prototype.ping = function(t) {
this.queue.push(t)
while(this.queue[0] < t - 3000) {
this.queue.shift()
}
return this.queue.length;
};
/**
* Your RecentCounter object will be instantiated and called as such:
* var obj = new RecentCounter()
* var param_1 = obj.ping(t)
*/
栈和队列的实现
用栈实现队列
使用栈实现队列的下列操作
push(x) -- 将一个元素放入队列的尾部。
pop() -- 从队列首部移除元素。
peek() -- 返回队列首部的元素。
empty() -- 返回队列是否为空。
MyQueue queue = new MyQueue();
queue.push(1);
queue.push(2);
queue.peek(); // 返回 1
queue.pop(); // 返回 1
queue.empty(); // 返回 false
来源: leetcode-cn.com/problems/im…
/**
* Initialize your data structure here.
*/
var MyQueue = function() {
this.stack1 = [];
this.stack2 = [];
};
/**
* Push element x to the back of queue.
* @param {number} x
* @return {void}
*/
MyQueue.prototype.push = function(x) {
this.stack1.push(x);
};
/**
* Removes the element from in front of queue and returns that element.
* @return {number}
*/
MyQueue.prototype.pop = function() {
if(this.stack2.length) {
return this.stack2.pop();
} else {
if(this.stack1.length) {
let len = this.stack1.length;
for (let i = 0; i < len; i++) {
this.stack2.push(this.stack1.pop())
}
return this.stack2.pop()
} else {
return null;
}
}
};
/**
* Get the front element.
* @return {number}
*/
MyQueue.prototype.peek = function() {
if(this.stack1.length === 0) {
return this.stack2[this.stack2.length - 1]
} else if(this.stack2.length === 0) {
return this.stack1[0]
}
};
/**
* Returns whether the queue is empty.
* @return {boolean}
*/
MyQueue.prototype.empty = function() {
if(this.stack1.length === 0 && this.stack2.length === 0) {
return true;
} else {
return false;
}
};
用队列实现栈
使用队列实现栈的下列操作:
push(x) -- 元素 x 入栈
pop() -- 移除栈顶元素
top() -- 获取栈顶元素
empty() -- 返回栈是否为空
来源: leetcode-cn.com/problems/im…
/**
* Initialize your data structure here.
*/
var MyStack = function() {
this.stack = [];
};
/**
* Push element x onto stack.
* @param {number} x
* @return {void}
*/
MyStack.prototype.push = function(x) {
this.stack[this.stack.length] = x;
return this.stack.length;
};
/**
* Removes the element on top of the stack and returns that element.
* @return {number}
*/
MyStack.prototype.pop = function() {
if(this.empty()) return undefined;
let value = this.stack[this.stack.length - 1];
this.stack.length -= 1;
return value;
};
/**
* Get the top element.
* @return {number}
*/
MyStack.prototype.top = function() {
return this.stack[this.stack.length -1];
};
/**
* Returns whether the stack is empty.
* @return {boolean}
*/
MyStack.prototype.empty = function() {
if(this.stack.length === 0) {
return true;
} else {
return false;
}
};
最小栈
设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。
push(x) —— 将元素 x 推入栈中。
pop() —— 删除栈顶的元素。
top() —— 获取栈顶元素。
getMin() —— 检索栈中的最小元素。
输入:
["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.
来源: leetcode-cn.com/problems/mi…
/**
* initialize your data structure here.
*/
var MinStack = function() {
this.stack = [];
this.min_stack = [];
};
/**
* @param {number} x
* @return {void}
*/
MinStack.prototype.push = function(x) {
this.stack.push(x);
if(this.min_stack.length === 0 || this.min_stack[this.min_stack.length - 1] >= x) {
this.min_stack.push(x)
}
};
/**
* @return {void}
*/
MinStack.prototype.pop = function() {
if(this.stack.pop() === this.min_stack[this.min_stack.length - 1]) {
this.min_stack.pop();
}
};
/**
* @return {number}
*/
MinStack.prototype.top = function() {
return this.stack[this.stack.length - 1]
};
/**
* @return {number}
*/
MinStack.prototype.getMin = function() {
return this.min_stack[this.min_stack.length - 1]
};
用两个栈实现队列
用两个栈实现一个队列。队列的声明如下,请实现它的两个函数 appendTail 和 deleteHead ,分别完成在队列尾部插入整数和在队列头部删除整数的功能。(若队列中没有元素,deleteHead 操作返回 -1 ) 。
push(x) —— 将元素 x 推入栈中。
pop() —— 删除栈顶的元素。
top() —— 获取栈顶元素。
getMin() —— 检索栈中的最小元素。
输入:
["CQueue","appendTail","deleteHead","deleteHead"]
[[],[3],[],[]]
输出:[null,null,3,-1]
来源: leetcode-cn.com/problems/yo…
var CQueue = function() {
this.inStack = [];
this.outStack = [];
};
/**
* @param {number} value
* @return {void}
*/
CQueue.prototype.appendTail = function(value) {
this.inStack.push(value)
};
/**
* @return {number}
*/
CQueue.prototype.deleteHead = function() {
let { inStack, outStack } = this;
if(outStack.length) {
return outStack.pop();
} else {
while(inStack.length) {
outStack.push(inStack.pop())
}
return outStack.pop() || -1;
}
};