栈 Stack
栈是一种具有特定行为的线性数据结构,遵循 后进先出(LIFO) 的原则。也就是说,最后放入栈的元素最先被取出。
栈的特点是 只能在栈顶进行插入(压栈)和删除(弹栈) 操作,其他位置的元素无法直接访问。类比现实生活中的栈,可以将其看作是一摞盘子,最后放入的盘子最先被取出。
括号匹配
-
一个字符串内部可能包含
{ }
( )
[ ]
三种括号,判断该字符串是否是括号匹配的。如({})
和[{()}]
就是匹配的,{a(b
和{a(b}c)
就是不匹配的。 -
思路:
- 遇到做括号 { [ ( 则压入栈
- 遇到右括号 } ] ) 则判断栈顶, 相同的则出栈
- 最后判断栈的长度是否为0
/**
* @param {string} s
* @return {boolean}
*/
function isValid(s) {
const stack = [];
const bracketMap = new Map([
["}", "{"],
["]", "["],
[")", "("],
]);
if (s.length % 2 !== 0) {
return false;
}
for (let char of s) {
// 判断Map中是否存在 {, (, [, 首先遇到开括号肯定不存在, 所以走else, 将开括号压入栈, 遇到闭括号进入if判断
if (bracketMap.has(char)) {
const top = stack.pop();
if (top !== bracketMap.get(char)) {
return false;
}
} else {
stack.push(char);
}
}
return stack.length === 0;
}
最小栈
- 思路:
- 我们需要维护一个辅助栈作为取最小栈的数组 min_stack
- 当一个元素要入栈, 我们取辅助栈的栈顶存储的最小值和需要入栈的元素做对比,取出最小值, 将最小值压入辅助栈, 这样辅助栈栈顶绝对是最小值
- 当一个元素要出栈, 除了需要对栈操作还需要对辅助栈弹出最小值
var MinStack = function () {
this.x_stack = [];
this.min_stack = [Infinity];
};
MinStack.prototype.push = function (x) {
this.x_stack.push(x);
this.min_stack.push(Math.min(this.min_stack[this.min_stack.length - 1], x));
};
MinStack.prototype.pop = function () {
this.x_stack.pop();
this.min_stack.pop();
};
MinStack.prototype.top = function () {
return this.x_stack[this.x_stack.length - 1];
};
MinStack.prototype.getMin = function () {
return this.min_stack[this.min_stack.length - 1];
};
删除有序数组中的重复项
- 思路:
- 使用双指针
- 让快指针走在最前面, 如果快指针的前一位和后一位不相等, 则慢指针当前的位置等于快指针位置的值, 同时慢指针往前移一位
/**
* 删除排序数组中的重复项
* 双指针
* @param {number[]} nums
* @returns {number}
* @description 给定一个数组[1, 2, 3, 4, 4, 5], 剔除重复的, 返回数组的长度, 数组是升序
*/
var removeDuplicates = function (nums) {
const n = nums.length;
if (n === 0) {
return 0;
}
let fast = 1, slow = 1;
while(fast < n) {
// 判断前一位和后一位不相等
if (nums[fast] !== nums[fast - 1]) {
nums[slow] = nums[fast];
++slow;
}
++fast;
}
return slow;
};