本文已参与「新人创作礼」活动,一起开启掘金创作之路。
| 每日一题做题记录,参考官方和三叶的题解 |
题目要求
代码注释
总结一下就是:
- 定义了一个名叫
NestedInteger的类; - 初始化调用
NestedInteger(value); isInteger():是否仅包含单个整数;getInteger():返回单个整数或;setInteger(value):使嵌套列表对象仅包含单个整数;add(ni):在当前嵌套列表中添加新的嵌套列表;getList():返回嵌套列表,若为单个整数返回。
思路一:栈
有点类似计算器的那个方法,运算符( & )和数字压入栈进行处理。
,:跳过,遍历下一位-或数字:[:]:
Java
class Solution {
int INF = 1000001;
public NestedInteger deserialize(String s) {
Deque<NestedInteger> stack = new ArrayDeque<>();
char[] cs = s.toCharArray();
int n = cs.length, i = 0;
while(i < n) {
if(cs[i] == ',' && ++i >= 0) //“,”跳过
continue;
if(cs[i] == '-' || (cs[i] >='0' && cs[i] <= '9')) { //负号或数字
int j = i + 1;
while(j < n && (cs[j] >= '0' && cs[j] <= '9')) //取出当前数字
j++;
stack.addLast(new NestedInteger(Integer.parseInt(s.substring(i,j))));
i = j;
}
else if(cs[i] == '[') {
stack.addLast(new NestedInteger());
stack.addLast(new NestedInteger(INF));
i++;
}
else { //“]”
List<NestedInteger> res = new ArrayList<>();
while(!stack.isEmpty()) {
NestedInteger cur = stack.pollLast(); //括号中间元素
if(cur.isInteger() && cur.getInteger() == INF) //是单独整数则get
break; //不是单独整数证明未找到上一个'['匹配的']',继续寻找
res.add(cur); //括号中间元素加入答案
}
for(int j = res.size() - 1; j >= 0; j--)
stack.peekLast().add(res.get(j)); //在栈顶元素末尾添加当前答案内容
i++;
}
}
return stack.peekLast();
}
}
- 时间复杂度:,遍历每一位。
- 空间复杂度:,栈的深度最大为,以及
toCharArray的长度为。
C++
class Solution {
int INF = 1000001;
public:
NestedInteger deserialize(string s) {
stack<NestedInteger> stack;
int n = s.size(), i = 0;
while(i < n) {
if(s[i] == ',' && ++i >= 0) //“,”跳过
continue;
if(s[i] == '-' || (s[i] >='0' && s[i] <= '9')) { //负号或数字
int j = i + 1;
while(j < n && (s[j] >= '0' && s[j] <= '9')) //取出当前数字
j++;
stack.emplace(NestedInteger(stoi(s.substr(i, j - i + 1))));
i = j;
}
else if(s[i] == '[') {
stack.emplace(NestedInteger());
stack.emplace(NestedInteger(INF));
i++;
}
else { //“]”
vector<NestedInteger> res;
while(!stack.empty()) {
NestedInteger cur = stack.top(); //括号中间元素
stack.pop();
if(cur.isInteger() && cur.getInteger() == INF) //是单独整数则get
break; //不是单独整数证明未找到上一个'['匹配的']',继续寻找
res.push_back(cur); //括号中间元素加入答案
}
for(int j = res.size() - 1; j >= 0; j--)
stack.top().add(res.at(j)); //在栈顶元素末尾添加当前答案内容
i++;
}
}
return stack.top();
}
};
- 时间复杂度:,遍历每一位。
- 空间复杂度:,栈的深度最大为。
思路二:递归
由题目和注释部分代码可知,NestedInteger内部要么是一个整数,要么是一堆整数构成的嵌套列表,明显是个递归定义,所以可以递归来遍历【DFS】:
[:表示解析嵌套列表,递归解析;,:嵌套列表内还有其他元素,需继续解析;]:当前列表解析完毕;-或数字:当前对象内仅包含一个整数,遍历后返回。
【用了和上面不一样的方法取数字,上面是找到位数返回子串转int(需额外标号统计位数),下面是逐位加回去(需额外变量存当前数,且负数需标记)】
Java
class Solution {
int idx = 0;
public NestedInteger deserialize(String s) {
char[] cs = s.toCharArray();
if(cs[idx] == '[') { //新的待解析对象
idx++;
NestedInteger ni = new NestedInteger();
while(cs[idx] != ']') { //解析完毕
ni.add(deserialize(s));
if(cs[idx] == ',') //还有其他元素
idx++;
}
idx++;
return ni;
}
else { //单个数字
boolean neg = false; //负数标识
if(cs[idx] == '-') {
neg = true;
idx++;
}
//将数字位加成一个整数,也可如思路一统计位数返回子字符串转int
int num = 0;
while(idx < cs.length && Character.isDigit(cs[idx])) {
num = num * 10 + cs[idx] - '0';
idx++;
}
if(neg)
num *= -1;
return new NestedInteger(num); //返回相应单个数字
}
}
}
- 时间复杂度:,遍历每一位。
- 空间复杂度:,深度优先搜索的深度最大为。
C++
class Solution {
public:
int idx = 0;
NestedInteger deserialize(string s) {
if(s[idx] == '[') { //新的待解析对象
idx++;
NestedInteger ni;
while(s[idx] != ']') { //解析完毕
ni.add(deserialize(s));
if(s[idx] == ',') //还有其他元素
idx++;
}
idx++;
return ni;
}
else { //单个数字
bool neg = false; //负数标识
if(s[idx] == '-') {
neg = true;
idx++;
}
//将数字位加成一个整数,也可如思路一统计位数返回子字符串转int
int num = 0;
while(idx < s.size() && isdigit(s[idx])) {
num = num * 10 + s[idx] - '0';
idx++;
}
if(neg)
num *= -1;
return NestedInteger(num); //返回相应单个数字
}
}
};
- 时间复杂度:,遍历每一位。
- 空间复杂度:,深度优先搜索的深度最大为。
总结
其实也是模拟题,模拟了好几天了……
题目自己定义了一个数据类型,要弄明白嵌套的是NestedInteger而不是int。
| 欢迎指正与讨论! |