一、栈_JavaScript数据结构与算法

栈是一个 后进先出 的数据结构。JavaScript 中没有栈,但可以用 Array 实现栈的所有功能

const stack = [];
stack.push(1);
stack.push(2);
const item1 = stack.pop();
const item2 = stack.pop();

栈应用场景

需要 后进先出Last in First out)的场景。日常生活中栈的应用:盘子、托盘、书堆等

  • 十进制转二进制
  • 判断字符串的括号是否有效
  • 函数调用堆栈
  • 文本编辑器、绘制程序中的撤销功能
  • Web 浏览器所访问过的链接的历史记录

十进制转二进制

  • 后出来的余数反而要排到前面
  • 把余数依次入栈,然后再出栈,就可以谁啊虚拟余数倒序输出

有效的括号

  • 越靠后的左括号,对应的有括号越靠前
  • 左括号入栈,右括号出栈,最后栈空了就是合法的

函数调用堆栈

  • 最后调用的函数,最后执行完
  • JS 解释器使用栈来控制函数的调用顺序
function greeting() {
  // ...
  sayHi()
}
function sayHi() {
  return 'Hi'
}
greeting()

20.有效的括号

20. 有效的括号

输入输出

给定一个只包括 '('')''{''}''['']' 的字符串 s ,判断字符串是否有效

输入:s = "()"
输出:true

输入:s = "()[]{}"
输出:true

输入:s = "(]"
输出:false

输入:s = "([)]"
输出:false

输入:s = "{[]}"
输出:true

题解

  • 对于没有闭合的左括号而言,越靠后的左括号,对应的右括号越靠前

    满足后进先出,考虑用栈

步骤

  • 新建一个栈,扫描字符串,遇左括号入栈,遇到和栈顶括号类型匹配的有括号就出栈,类型不匹配直接判定为不合法,最后栈空了就合法,否则不合法
var isValid = function (s) {
  if (s.length % 2 === 1) return false
  const stack = []
  for (let i = 0; i < s.length; i++) {
    const c = s[i]
    if (c === '(' || c === '{' || c === '[') {
      stack.push(c)
    } else {
      const t = stack[stack.length - 1]
      if ((t === '(' && c === ')') || (t === '{' && c === '}') || (t === '[' && c === ']')) {
        stack.pop()
      } else {
        return false
      }
    }
  }
  return stack.length === 0
}

时间复杂度:O(n)

空间复杂度:O(n)

其他解法

var isValid = function (s) {
  if (s.length % 2 === 1) return false
  const stack = []
  for (let ch of s) {
    switch (ch) {
      case '(':
      case '[':
      case '{':
        stack.push(ch)
        break
      case '}':
        if (stack.pop() !== '{') return false
        break
      case ']':
        if (stack.pop() !== '[') return false
        break
      case ')':
        if (stack.pop() !== '(') return false
        break
    }
  }
  return !stack.length
}
  • 使用 Map 数据结构
var isValid = function (s) {
  if (s.length % 2 === 1) return false
  const stack = []
  const map = new Map([
    [')', '('],
    [']', '['],
    ['}', '{'],
  ])
  for (const ch of s) {
    if (map.has(ch)) {
      if (stack.pop() !== map.get(ch)) return false
    } else {
      stack.push(ch)
    }
  }
  return !stack.length
}

思考题

ES6 封装栈

  • push :添加一个元素到栈顶
  • pop :移除栈顶元素
  • peek :返回栈顶元素
  • size :返回栈里元素的个数
class Stack {
  constructor() {
    this.items = []
  }
  push(item) {
    return this.items.push(item)
  }
  pop() {
    return this.items.pop()
  }
  peek() {
    return this.items[this.items.length - 1]
  }
  size() {
    return this.items.length
  }
}

十进制转二进制

  • 除以二,得到的余数是从低到高的次序,而输出是从高到低,所以需要栈来反转
function baseConvert(num, base) {
  const stack = []
  const digits = '0123456789ABCDEF'
  let res = ''
  while (num > 0) {
    rem = num % base
    num = Math.floor(num / base)
    stack.push(rem)
  }
  while (stack.length !== 0) {
    res += digits[stack.pop()]
  }
  return res
}
baseConvert(25, 2)
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值