[ 栈 ]385. 迷你语法分析器

151 阅读1分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第15天,点击查看活动详情

每日刷题 2021.04.15

题目

  • 给定一个字符串 s 表示一个整数嵌套列表,实现一个解析它的语法分析器并返回解析的结果 NestedInteger 。
  • 列表中的每个元素只可能是整数或整数嵌套列表

示例

  • 示例1
输入: s = "324",
输出: 324
解释: 你应该返回一个 NestedInteger 对象,其中只包含整数值 324。
  • 示例2
输入:s = "[123,[456,[789]]]",
输出:[123,[456,[789]]]
解释:返回一个 NestedInteger 对象包含一个有两个元素的嵌套列表:
1. 一个 integer 包含值 123
2. 一个包含两个元素的嵌套列表:
    i.  一个 integer 包含值 456
    ii. 一个包含一个元素的嵌套列表
         a. 一个 integer 包含值 789

提示

  • 1 <= s.length <= 5 * 10^4
  • s 由数字、方括号 "[]"、负号 '-' 、逗号 ','组成
  • 用例保证 s 是可解析的 NestedInteger
  • 输入中的所有值的范围是 [-10^6, 10^6]

解题思路

  • 本题的题意比较难理解,其次它的解法也比较难想到。

题意

  • 根据,题目中所给的注解,可以看到NestedInteger是一个对象,其可以调用isInteger()、add()等方法。
  • 单靠不太顺畅的英文阅读能力去理解,有可能会出现偏差,因此我们可以通过对象调用方法,来直观的查看到每个函数的实际意义。
let ans = new NestedInteger();    // ans = []
ans.add(new NestedInteger(789));  // ans = [789]
let temp = new NestedInteger();   // temp = []
temp.add(new NestedInteger(456));   // temp = [456]
temp.add(ans);                      // temp = [456, [789]]
let res = new NestedInteger();      // res = []
res.add(new NestedInteger(123));    // res = [123]
res.add(temp);                      // res = [123, [456, [789]]]
  • 大致的意思,就是需要利用构造函数构造一个和字符串 s 一样的嵌套列表

解题

  • 在理解了题意之后,如果你之前做过有效的括号这道题,那么求解本题就会比较容易,思路大致上是一致的。
  • 有效的括号:需要一个栈来存储每次遇到的右括号(依次压入栈中),当遇到左括号的时候,就将与之匹配的右括号出栈。如果栈顶不是与之匹配的右括号,那么就直接返回false,并不是有效的括号;如果所有的左括号都可以找到与之匹配的右括号,那么这就是有效的括号,返回true
  • 本题:对于前面出现的数字,我们可以将其更新好之后,放在栈底部。最新的结果处理完成后,再将前面存储的从栈中弹出来,嵌套起来后,重新将其压入栈中。遇到以下的几种情况,如何处理?
    • [,创建一个NestedInteger对象
    • 数字,将所有的数字都记录在字符串str
    • ,,判断当前str是否为空字符串,如果为空字符串,那么就直接跳过;如果不为空字符串,就将其加入到栈顶的元素中。
    • ],判断当前的str是否为空字符串,如果是空字符串,那么就直接跳过;如果不是空字符串,就将其加入到栈顶的元素中。还需要额外的判断,栈中的元素是否包含1个以上,如果包含1个以上,需要将栈中的多个合并嵌套成为一个列表
  • 举个例子 89076934b36054352f5700b748b2b27.jpg

AC代码

/**
 * // This is the interface that allows for creating nested lists.
 * // You should not implement it, or speculate about its implementation
 * function NestedInteger() {
 *     Return true if this NestedInteger holds a single integer, rather than a nested list.
 *     @return {boolean}
 *     this.isInteger = function() {
 *         ...
 *     };
 *
 *     Set this NestedInteger to hold a nested list and adds a nested integer elem to it.
 *     @return {void}
 *     this.add = function(elem) {
 *         ...
 *     };
 *
 *     Return the nested list that this NestedInteger holds, if it holds a nested list
 *     Return null if this NestedInteger holds a single integer
 *     @return {NestedInteger[]}
 *     this.getList = function() {
 *         ...
 *     };
 * };
 */
/**
 * @param {string} s
 * @return {NestedInteger}
 */
var deserialize = function(s) 
  // 栈模拟分几种情况
  // 遇到[] ,的情况讨论
  // 分三种情况:
  // [ ] , 
  const len = s.length;
  // 预处理操作
  if(s[0] != '[') {
    const nest = new NestedInteger(s);
    return nest;
  }
  let stack = [], str = '';
  for(let i = 0; i < len; i++) {
    if(s[i] == '['){
      stack.push(new NestedInteger());
    }else if(s[i] == ']'){
      if(str != ''){
        // 没有需要添加的
        let cur = stack.pop();
        cur.add(new NestedInteger(str));
        stack.push(cur);
        str = '';
      }
      if (stack.length > 1) {
        let cur = stack.pop();
        let pre = stack.pop();
        pre.add(cur);
        stack.push(pre);
      }
    }else if(s[i] == ','){
      if(str != ''){
        let cur = stack.pop();
        cur.add(new NestedInteger(str));
        stack.push(cur);
        str = '';
      }
    }else {
      str += s[i];
    }
  }
  return stack.pop()
};

总结

  • 对于使用栈数据结构的题目,一定要想清除,为什么要使用这种数据结构,以此来解决什么样的问题。
  • 栈数据结构:先进后出