JS: 数据结构与算法之栈
栈
先来看一道题
Leetcode 32 Longest Valid Parentheses (最长有效括号)
给定一个只包含
'('和')'的字符串,找出最长的包含有效括号的子串的长度。示例 1:
输入: "(()"
输出: 2
解释: 最长有效括号子串为 "()"
示例 2:
输入: ")()())"
输出: 4
解释: 最长有效括号子串为 "()()"
这道题可以用动态规划来做,也能用简洁明了的栈来解决。
什么是栈?
栈是一种先进后出(LIFO)的有序集合,新添加的元素在栈顶,旧元素在栈底。
以下图为例,1、2、3、4、5、6、7先后进栈:

创建栈
创建一个类来表示栈:
class Stack {
// 初始化类,创建数组 items 存放入栈元素
constructor() {
this.items = [];
}
// push 方法进行元素入栈(可同时入栈一或多个元素),无返回值
push() {
this.items.push(...arguments);
}
// pop 方法出栈一个元素,返回出栈元素
pop() {
return this.items.pop();
}
// peek 方法返回栈顶元素,不对栈本身做任何操作
peek() {
return this.items[this.items.length-1];
}
// size 方法返回栈内元素个数
size() {
return this.items.length;
}
// isEmpty 方法查看栈是否为空,返回布尔值
isEmpty() {
return this.items.length == 0;
}
// clear 方法清空栈,无返回值
clear() {
this.items = [];
}
// print 方法打印栈内元素
print() {
console.log(this.items.toString());
}
}
// 测试
let stack = new Stack();
stack.push(1,2,3,4);
stack.print(); // 1,2,3,4
stack.isEmpty(); // false
stack.size(); // 4
stack.pop(); // 4
stack.peek(); // 3
stack.clear();
注意
因为 JavaScript 的类内暂时无法定义私有成员,所以可以在类外访问到存储栈元素的数组 items,这个操作是很危险的。
stack.items; // [1, 2, 3, 4]
这时可以使用闭包和IIFE进行避免,这是一个很无奈的办法:
let Stack = (function () {
// 使用 WeakMap 存储数组(数组存放进栈元素)
let items = new WeakMap();
class Stack {
constructor() {
items.set(this, []);
}
push() {
items.get(this).push(...arguments);
}
// 其他方法
}
return Stack;
})();
let s = new Stack();
// 无法访问到 items
s.items; // undefined
WeakMap: WeakMap是类似Map的键值对集合,但WeakMap的键是弱引用的,只要不存在引用,垃圾回收机制就会回收掉占用的内存,相当于自动删除,而不用手动删除。
用栈解题
思路:
- 变量
start存放有效括号起始下标,maxLen存放最大长度; - 栈只存放左括号的下标,遇到左括号,将其下标存入栈中;
- 遇到右括号,若此时栈为空,跳过本次循环并更新
start;若栈不为空,则栈顶元素出栈; - 栈顶元素出栈后,若栈为空,则计算当前下标和
start的距离,并更新maxLen; - 栈顶元素出栈后,若栈不为空,则计算当前下标和栈顶存放的下标的距离,并更新
maxLen; - 循环遍历直至结束。
function test(str) {
let stack = new Stack();
let start = 0;
let maxLen = 0;
for(let i=0; i<str.length; i++) {
// 如果是左括号,下标入栈
if (str[i] == '(') {
stack.push(i);
} else {
// 如果是右括号
/* 栈内为空,说明本次有效括号匹配已结束,跳过本次循环并更新 start */
if (stack.isEmpty()) {
start = i+1;
continue;
} else {
// 栈内不为空,则出栈一个左括号进行匹配
stack.pop();
// 栈顶元素出栈后,栈为空
if (stack.isEmpty()) {
// 根据当前下标和 start 去更新 maxLen
maxLen = Math.max(maxLen, i-start+1);
} else {
// 栈不为空,根据当前下标和栈顶存放的下标去更新 maxLen
maxLen = Math.max(maxLen, i-stack.peek());
}
}
}
}
return maxLen;
}
test('(()'); // 2
test(')()())'); // 4
备注
终于从大半个月的考试和课设中解放出来了,每天早起晚睡,还是很累的。
JS: 数据结构与算法之栈的更多相关文章
- JS数据结构与算法——栈
JS数据结构与算法--栈 1.栈结构概念 栈(Stack)是一种先进后出(LIFO Last in First out)的线性表,先进栈的将会比后进栈的先出栈. 栈的限制是仅允许在一端进行插入和删除运 ...
- JS数据结构与算法-概述
JS数据结构与算法概述 数据结构: 计算机存储, 组织数据的方式, 就像锅碗瓢盆 算法: 一系列解决问题的清晰指令, 就像食谱 两者关系: 程序 = 数据结构 + 算法 邂逅数据结构与算法 什么是数据 ...
- 【Java数据结构学习笔记之二】Java数据结构与算法之栈(Stack)实现
本篇是java数据结构与算法的第2篇,从本篇开始我们将来了解栈的设计与实现,以下是本篇的相关知识点: 栈的抽象数据类型 顺序栈的设计与实现 链式栈的设计与实现 栈的应用 栈的抽象数据类型 栈是 ...
- java数据结构与算法之栈(Stack)设计与实现
本篇是java数据结构与算法的第4篇,从本篇开始我们将来了解栈的设计与实现,以下是本篇的相关知识点: 栈的抽象数据类型 顺序栈的设计与实现 链式栈的设计与实现 栈的应用 栈的抽象数据类型 栈是一种用于 ...
- JS数据结构及算法(一) 堆栈
最近在看<学习JavaScript数据结构与算法>这本书,感觉自己又涨知识了 哈哈... 现在将自己看的做个总结,也是巩固理解. 栈:先进后出,新添加和待删除的元素都保存在栈顶.可以用数组 ...
- Java数据结构和算法(一)--栈
栈: 英文名stack,特点是只允许访问最后插入的那个元素,也就是LIFO(后进先出) jdk中的stack源码: public class Stack<E> extends Vector ...
- JS数据结构第四篇 --- 栈
一.什么是数据结构栈 在数据结构中有一个栈结构,在内存空间中也有一个栈空间,这两个”栈“是两个不同的概念.这篇我们说的是数据结构中的栈.栈是一种特殊的线性表,特殊性在哪?就是只能在栈顶进行操作,往栈顶 ...
- C语言- 基础数据结构和算法 - 09 栈的应用_中缀表达式转后缀表达式20220611
09 栈的应用_中缀表达式转后缀表达式20220611 听黑马程序员教程<基础数据结构和算法 (C版本)>, 照着老师所讲抄的, 视频地址https://www.bilibili.com/ ...
- C语言- 基础数据结构和算法 - 08 栈的应用_就近匹配20220611
听黑马程序员教程<基础数据结构和算法 (C版本)>, 照着老师所讲抄的, 视频地址https://www.bilibili.com/video/BV1vE411f7Jh?p=1 喜欢的朋友 ...
随机推荐
- SQL0973N在 "<堆名>" 堆中没有足够的存储器可用来处理语句
SQL0973N在 "<堆名>" 堆中没有足够的存储器可用来处理语句. 解释: 已使用此堆的所有可用内存.不能处理该语句. 用户响应: 接收到此消息(SQLCODE)后 ...
- Silverlight或WPF动态绑定图片路径问题,不用Converter完美解决
关于Silverlight或WPF动态绑定图片路径问题,不用Converter完美解决, 可想,一个固定的字符串MS都能找到,按常理动态绑定也应该没问题的,只需在前面标记它是一个Path类型的值它就能 ...
- Phantomjs 生成多页PDF
开篇 最近使用 Phantomjs 生成PDF,其中遇到一些问题,导致PDF生成失败,如出现空白文件或一页数据量太大,都是由于没有设置好格式导致.特别是分页问题,感觉资料很少,除了在 StackOve ...
- 负值之美:负margin在页面布局中的应用
本文转载自:http://www.topcss.org/?p=94,有修改. 负数给人总是一种消极.否定.拒绝之感,不过有时利用负margin可以达到奇妙的效果,今天就表一表负值在页面布局中的应用.这 ...
- 乞丐版servlet容器第3篇
4 EventListener接口 让我们继续看SocketConnector中的acceptConnect方法: @Override protected void acceptConnect() t ...
- Deployment failure on Tomcat 6.x. Could not copy all resources to D:\...\webapps\eptInfo. If a file is locked, you can wait until the lock times out to redeploy, or stop the server and redeploy, or ma
tomcat服务并没有启动.工程中之前引了一个包,后来这个包被删除了,但是因为已经发布过这个工程了,所以classpath中就有这个包名了,这样发布的时候也会去找这个包但是已经不存在了,所以无copy ...
- 进度条ProgressBar
在本节中,作者只写出了进度条的各种样式,包括圆形.条形,还有自定义的条形,我想如果能让条形进度条走满后再继续从零开始,于是我加入了一个条件语句.作者的代码中需要学习的是handler在主线程和子线程中 ...
- pyhthon lambda
lambda x:x+1(1) >>>2 可以这样认为,lambda作为一个表达式,定义了一个匿名函数,上例的代码x为入口参数和出口参数,x+1为函数体,(1)为x的入口初始值, 用 ...
- MySQL性能调优与架构设计——第 18 章 高可用设计之 MySQL 监控
第 18 章 高可用设计之 MySQL 监控 前言: 一个经过高可用可扩展设计的 MySQL 数据库集群,如果没有一个足够精细足够强大的监控系统,同样可能会让之前在高可用设计方面所做的努力功亏一篑.一 ...
- Trystrtofloat
TryStrToFloat为 ‘+1’和‘-1’和 ‘.1’是可以装换成功的