JavaScript数据结构之栈实例用法


Posted in Javascript onJanuary 18, 2019


先来看一道题

Leetcode 32 Longest Valid Parentheses (最长有效括号)

给定一个只包含 '(' 和 ')' 的字符串,找出最长的包含有效括号的子串的长度。

示例 1:

输入: "(()"
输出: 2
解释: 最长有效括号子串为 "()"

示例 2:

输入: ")()())"
输出: 4
解释: 最长有效括号子串为 "()()"

这道题可以用动态规划来做,也能用简洁明了的栈来解决。

什么是栈?

栈是一种先进后出(LIFO)的有序集合,新添加的元素在栈顶,旧元素在栈底。

以下图为例,1、2、3、4、5、6、7先后进栈:

JavaScript数据结构之栈实例用法

创建栈

创建一个类来表示栈:

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
Javascript 相关文章推荐
js原生appendChild的bug解决心得分享
Jul 01 Javascript
jQuery使用$.ajax进行异步刷新的方法(附demo下载)
Dec 04 Javascript
jQuery回到顶部的代码
Jul 09 Javascript
利用jQuery来动态为属性添加或者删除属性的简单方法
Dec 02 Javascript
利用Vue v-model实现一个自定义的表单组件
Apr 27 Javascript
jquery实现限制textarea输入字数的方法
Sep 06 jQuery
JavaScript数组push方法使用注意事项
Oct 30 Javascript
微信小程序分享海报生成的实现方法
Dec 10 Javascript
使用layui监听器监听select下拉框,事件绑定不成功的解决方法
Sep 28 Javascript
微信小程序返回上一页传参并刷新过程解析
Dec 13 Javascript
jquery添加div实现消息聊天框
Feb 08 jQuery
Vue项目中如何封装axios(统一管理http请求)
May 02 Vue.js
Vue核心概念Action的总结
Jan 18 #Javascript
js取小数点后两位四种方法
Jan 18 #Javascript
jQuery移动端跑马灯抽奖特效升级版(抽奖概率固定)实现方法
Jan 18 #jQuery
jquery获取file表单选择文件的路径、名字、大小、类型
Jan 18 #jQuery
jQuery实现适用于移动端的跑马灯抽奖特效示例
Jan 18 #jQuery
js数组去重的方法总结
Jan 18 #Javascript
jQuery实现的3D版图片轮播示例【滑动轮播】
Jan 18 #jQuery
You might like
php四种基础算法代码实例
2013/10/29 PHP
在openSUSE42.1下编译安装PHP7 的方法
2015/12/24 PHP
thinkPHP删除前弹出确认框的简单实现方法
2016/05/16 PHP
php类自动装载、链式操作、魔术方法实现代码
2017/07/23 PHP
PHP后台实现微信小程序登录
2018/08/03 PHP
解决 firefox 不支持 document.all的方法
2007/03/12 Javascript
JavaScript Date对象使用总结
2009/05/14 Javascript
Jquery多选下拉列表插件jquery multiselect功能介绍及使用
2013/05/24 Javascript
jquery 按键盘上的enter事件
2014/05/11 Javascript
jquery编写Tab选项卡滚动导航切换特效
2020/07/17 Javascript
探究Vue.js 2.0新增的虚拟DOM
2016/10/20 Javascript
微信小程序 picker 组件详解及简单实例
2017/01/10 Javascript
基于bootstrap实现收缩导航条
2017/03/17 Javascript
vue-cli开发环境实现跨域请求的方法
2018/04/07 Javascript
vue项目打包部署到服务器的方法示例
2018/08/27 Javascript
vue项目在线上服务器访问失败原因分析
2020/08/14 Javascript
[01:08:17]2018DOTA2亚洲邀请赛3月29日 小组赛B组 EG VS VGJ.T
2018/03/30 DOTA
Python的Django框架中从url中捕捉文本的方法
2015/07/20 Python
Python实现Linux的find命令实例分享
2017/06/04 Python
PyQt5每天必学之拖放事件
2020/08/27 Python
Python简单定义与使用二叉树示例
2018/05/11 Python
python 统计列表中不同元素的数量方法
2018/06/29 Python
解决python3捕获cx_oracle抛出的异常错误问题
2018/10/18 Python
使用Python脚本zabbix自定义key监控oracle连接状态
2019/08/28 Python
详解pandas获取Dataframe元素值的几种方法
2020/06/14 Python
使用Python绘制台风轨迹图的示例代码
2020/09/21 Python
幼儿园开学家长寄语
2014/01/19 职场文书
中学生演讲稿
2014/04/26 职场文书
社区平安建设汇报材料
2014/08/14 职场文书
小学教师师德师风个人整改措施
2014/09/18 职场文书
精神病医院见习报告
2014/11/03 职场文书
2014年助理政工师工作总结
2014/12/19 职场文书
优秀员工事迹材料
2014/12/20 职场文书
2015年教师工作总结范文
2015/03/31 职场文书
nginx proxy_cache 缓存配置详解
2021/03/31 Servers
springboot读取nacos配置文件
2022/05/20 Java/Android