力扣每日一题0415-385. 迷你语法分析器

69 阅读2分钟

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

给定一个字符串 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<=5104`1 <= s.length <= 5 * 10^4`
  • s 由数字、方括号 "[]"、负号 '-' 、逗号 ','组成
  • 用例保证 s 是可解析的 NestedInteger
  • 输入中的所有值的范围是 [106,106]`[-10^6, 10^6]`

深度优先搜索

根据题意,一个 NestedInteger\texttt{NestedInteger} 实例只能包含下列两部分之一:1)一个整数;2)一个列表,列表中的每个元素都是一个 NestedInteger\texttt{NestedInteger} 实例。据此,NestedInteger\texttt{NestedInteger} 是通过递归定义的,因此也可以用递归的方式来解析。

从左至右遍历 ss

  • 如果第一位是 ‘[’\texttt{`['} 字符,则表示待解析的是一个列表,从 ‘[’\texttt{`['} 后面的字符开始又是一个新的 NestedInteger\texttt{NestedInteger} 实例,我们仍调用解析函数来解析列表的元素,调用结束后如果遇到的是 ,, 字符,表示列表仍有其他元素,需要继续调用。如果是 ‘]’\texttt{`]'}字符,表示这个列表已经解析完毕,可以返回 NestedInteger\texttt{NestedInteger} 实例。
  • 否则,则表示待解析的 NestedInteger\texttt{NestedInteger} 只包含一个整数。我们可以从左至右解析这个整数,并注意是否是负数,直到遍历完或者遇到非数字字符 (]’(\texttt{]'},’\texttt{,'}),并返回 NestedInteger\texttt{NestedInteger} 实例。
var deserialize = function(s) {
    let index = 0;
    const dfs = (s) => {
        if (s[index] === '[') {
            index++;
            const ni = new NestedInteger();
            while (s[index] !== ']') {
                ni.add(dfs(s));
                if (s[index] === ',') {
                    index++;
                }
            }
            index++;
            return ni;
        } else {
            let negative = false;
            if (s[index] === '-') {
                negative = true;
                index++;
            }
            let num = 0;
            while (index < s.length && isDigit(s[index])) {
                num = num * 10 + s[index].charCodeAt() - '0'.charCodeAt();
                index++;
            }
            if (negative) {
                num *= -1;
            }
            return new NestedInteger(num);
        }
    }
    return dfs(s);
};

const isDigit = (ch) => {
    return parseFloat(ch).toString() === "NaN" ? false : true;
}