问题描述
给定一个字符串 s 表示一个整数嵌套列表,实现一个解析它的语法分析器并返回解析的结果 NestedInteger 。
列表中的每个元素只可能是整数或整数嵌套列表。
示例:
输入: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 来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/mini-parser 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路
基本想法
观察示例输入,发现输入的字符串可以粗分类为:①.纯整数(正负数均可),②.' [ ' 开头的合法的整数列表(含嵌套)。对于第①种输入,直接进行字符串转整数的函数操作即可(string里有现成的stoi()函数来进行此步操作),对于第②种输入,基本思想是先根据括号匹配的思路,将每个' [ ' 和 ' ] ' 压栈弹栈,进而得到最终输出。对于中间出现的数字字符子串,则可以直接获取这些数字字符对应的整数压入当前栈顶进行处理。该题本质上就是反序列化,也即将字符串等数据转化为程序可处理的对象或变量,所以在题目给的编写样板里函数的名字为deserialize。
示例过程可视化演示
其中:①③⑤为识别到 '[' :需要将新的空列表压栈,②④⑥为识别到数字相关符号('0' ~ '9'及'-'):需要将数字字符相关的内容转换为整数类型添加在当前栈顶的列表中,⑦⑧⑨为识别到']':需要记录当前栈顶的列表并弹栈,如果栈中还有未弹出的列表,加入到更新后的栈顶列表中。
实际上在上述图例中,此问题的基本解决思路已经一目了然了,只需再考虑对应的一些边界条件处理就能真正解决此问题了。边界条件是当栈彻底清空时,此时弹出的元素就是我们需要的最终列表,可以使用一个NestedInterger来存储该列表并返回,这样得到的自然就是最终答案。
完整代码(C++)
/**
* // This is the interface that allows for creating nested lists.
* // You should not implement it, or speculate about its implementation
* class NestedInteger {
* public:
* // Constructor initializes an empty nested list.
* NestedInteger();
*
* // Constructor initializes a single integer.
* NestedInteger(int value);
*
* // Return true if this NestedInteger holds a single integer, rather than a nested list.
* bool isInteger() const;
*
* // Return the single integer that this NestedInteger holds, if it holds a single integer
* // The result is undefined if this NestedInteger holds a nested list
* int getInteger() const;
*
* // Set this NestedInteger to hold a single integer.
* void setInteger(int value);
*
* // Set this NestedInteger to hold a nested list and adds a nested integer to it.
* void add(const NestedInteger &ni);
*
* // Return the nested list that this NestedInteger holds, if it holds a nested list
* // The result is undefined if this NestedInteger holds a single integer
* const vector<NestedInteger> &getList() const;
* };
*/
class Solution {
private:
int getInt(string &s, int &index) { //数字字符转整数的实现函数
int sz = s.size();
bool negFlag = false; // flag of the number (sgn(x))
int val = 0;
if(s[index] == '-') {
negFlag = true;
index++;
}
while(index < sz && s[index] >= '0' && s[index] <= '9') {
val = val * 10 + s[index] - '0';
index++;
}
return negFlag ? -val : val;
}
public:
NestedInteger deserialize(string s) {
if(*s.begin() != '[') { //数字或负号开头的字符串直接转化为整型变量
return NestedInteger(stoi(s));
}
deque<NestedInteger> stk;
int num = 0; //数字字符转整数的中间变量
int index = 0; //当前的字符串指针指向点,初始时指向字符串头部(0)处
//bool flag = false;
NestedInteger res = NULL; //res记录最终需要的结果
while(index < s.size()) {
if(s[index] == '[') { //'['表示需要在栈顶添加新列表
stk.push_front(NestedInteger());
index++;
} else if(s[index] == '-' || (s[index] >= '0' && s[index] <= '9')) {
num = getInt(s, index); //获取当前数字字符序列对应的整数
stk.front().add(NestedInteger(num)); //当前栈顶的列表加入刚转化的整数
} else if(s[index] == ',') {
index++; //','仅做分割符使用
} else if(s[index] == ']') { //']'表示需要弹栈
res = stk.front();//记录栈顶元素,防止弹栈后栈为空无法保存结果
stk.pop_front();
if(stk.empty()) //弹栈后发现栈为空,如果不加入新列表,临时结果无法存储进栈
stk.push_front(NestedInteger());
stk.front().add(res);
index++;
}
}
/* 此处为for循环写法,并且在这块部分中,getInt()函数不封装
for(int i = 0; i < s.size(); i++) {
if(s[i] == '[') {
stk.push_front(NestedInteger());
}
if(s[i] == '-') {
flag = true;
}
if(s[i] >= '0' && s[i] <= '9') {
num = num * 10 + s[i] - '0';
}
if(s[i] == ',' || s[i] == ']') {
if(s[i - 1] >= '0' && s[i - 1] <= '9') {
if(flag) {
num *= -1;
}
stk.front().add(NestedInteger(num));
}
num = 0;
flag = false;
if(s[i] == ']' && stk.size() > 1) {
NestedInteger ni = stk.front();
stk.pop_front();
stk.front().add(ni);
}
}
}
return stk.front();
*/
return res;
}
};