一、定义
栈(Stack)是一种常见的数据结构,它遵循后进先出(LIFO,Last-In-First-Out)的原则。类比于现实生活中的栈,比如一摞书,你只能从最顶端取出或放入书籍,而不能从中间或底部进行操作。
二、封装栈结构
栈具有以下两个主要操作:
入栈(Push):将元素压入栈顶。出栈(Pop):从栈顶移除一个元素,并返回该元素。
栈还可能包含其他辅助操作,如:
栈顶元素访问(Peek):获取栈顶的元素值,但不对栈进行修改。栈的大小(Size):返回栈中元素的数量。栈是否为空(isEmpty):检查栈是否为空,如果为空则返回 true,否则返回 false。
class Stack {
constructor() {
this.items = [];
}
push(element) {
this.items.push(element);
}
pop() {
if (this.isEmpty()) {
return null;
}
return this.items.pop();
}
peek() {
if (this.isEmpty()) {
return null;
}
return this.items[this.items.length - 1];
}
size() {
return this.items.length;
}
isEmpty() {
return this.items.length === 0;
}
}
三、拓展
1. 单调栈
1. 定义
单调栈(Monotonic Stack)是一种常见的算法技巧,主要用于解决一些与单调性相关的问题。单调栈的基本思想是维护一个栈,栈内的元素满足一定的单调性。对于单调递增栈来说,栈内元素从栈底到栈顶是递增的;对于单调递减栈来说,栈内元素从栈底到栈顶是递减的。- 它通常用于寻找数组中元素的下一个更大或更小的元素。
- 时间复杂度是
O(n)
2. 代码模板
function monotoneStack(数据参数){
//定义一个结果容器
const stack = []
//从右边开始查找是逆序
for(遍历数据){
//保证栈顶是最大的或最小的
while(stack.length && 满足一个判断条件){
出栈操作
}
其他的一些计算
入栈操作
}
返回结果
}
3. 应用
- [496] 下一个更大元素
- 题目描述:
- 给定两个没有重复元素的数组 nums1 和 nums2 ,其中nums1 是 nums2 的子集。找到 nums1 中每个元素在 nums2 中的下一个比其大的值。
- nums1 中数字 x 的下一个更大元素是指 x 在 nums2 中对应位置的右边的第一个比 x 大的元素。如果不存在,对应位置输出-1。
- 代码实现
/**
* @param {number[]} nums1
* @param {number[]} nums2
* @return {number[]}
*/
var nextGreaterElement = function (nums1, nums2) {
//O(m+n)
let m = nums1.length;
let n = nums2.length;
const stack = [];//单调栈
const resMap = new Map();
//找出nums2每个元素,右边更大的元素
for (let i = n - 1; i >= 0; i--) {
//保证栈顶是最大的
while (stack.length > 0 && stack[stack.length - 1] <= nums2[i]) {
stack.pop();
}
resMap.set(nums2[i], stack.length > 0 ? stack[stack.length - 1] : -1);
stack.push(nums2[i]);
}
const res = [];
for (let i = 0; i < m; i++) {
res.push(resMap.get(nums1[i]));
}
return res;
}