问题:
Given a nested list of integers represented as a string, implement a parser to deserialize it.
Each element is either an integer, or a list -- whose elements may also be integers or other lists.
Note: You may assume that the string is well-formed:
- String is non-empty.
- String does not contain white spaces.
- String contains only digits
0-9
,[
,-
,
,]
.
Example 1:
Given s = "324", You should return a NestedInteger object which contains a single integer 324.
Example 2:
Given s = "[123,[456,[789]]]", Return a NestedInteger object containing a nested list with 2 elements: 1. An integer containing value 123. 2. A nested list containing two elements: i. An integer containing value 456. ii. A nested list with one element: a. An integer containing value 789.
解决:
【题意】这道题让我们实现一个迷你解析器用来把一个字符串解析成NestInteger类。
对输入的每个字符进行判断
数字: 用l保存开始 用i保存数字最后一位的下一位 用substring进行裁剪
字符‘[’ :遇到 [ 时将上一级的NestedInteger保存入栈 进行下一步操作
字符’]’:判断是否需要将数字加入当前NestedInteger,然后将上一级NestedInteger弹出 将这一级的NestedInteger加入到上一级的NestedInteger中去
字符’,’判断是否要将数字加入当前NestedInteger
① 递归方法解决。首先判断s是否为空,为空直接返回,不为空的话看首字符是否为'[',不是的话说明s为一个整数,我们直接返回结果。如果首字符是'[',且s长度小于等于2,说明没有内容,直接返回结果。反之如果s长度大于2,我们从i=1开始遍历,我们需要一个变量start来记录某一层的起始位置,用count来记录跟起始位置是否为同一深度,count=0表示同一深度,由于中间每段都是由逗号隔开,所以当我们判断当count为0,且当前字符是逗号或者已经到字符串末尾了,我们把start到当前位置之间的字符串取出来递归调用函数,把返回结果加入res中,然后start更新为i+1。如果遇到'[',计数器count自增1,若遇到']',计数器count自减1。
class Solution { //17ms
public NestedInteger deserialize(String s) {
NestedInteger res = new NestedInteger();
if (s == null || s.length() == 0) return res;
if (s.charAt(0) != '[') {
res.setInteger(Integer.parseInt(s));
} else if (s.length() > 2) {
int start = 1, count = 0;
for (int i = 1; i < s.length(); i++) {
char c = s.charAt(i);
if (count == 0 && (c == ',' || i == s.length() - 1)) {
res.add(deserialize(s.substring(start, i)));
start = i + 1;
}
else if (c == '[') count++;
else if (c == ']') count--;
}
}
return res;
}
}
② 非递归方法,用栈维护一个包含关系。
/**
* // This is the interface that allows for creating nested lists.
* // You should not implement it, or speculate about its implementation
* public interface NestedInteger {
* // Constructor initializes an empty nested list.
* public NestedInteger();
*
* // Constructor initializes a single integer.
* public NestedInteger(int value);
*
* // @return true if this NestedInteger holds a single integer, rather than a nested list.
* public boolean isInteger();
*
* // @return the single integer that this NestedInteger holds, if it holds a single integer
* // Return null if this NestedInteger holds a nested list
* public Integer getInteger();
*
* // Set this NestedInteger to hold a single integer.
* public void setInteger(int value);
*
* // Set this NestedInteger to hold a nested list and adds a nested integer to it.
* public void add(NestedInteger ni);
*
* // @return the nested list that this NestedInteger holds, if it holds a nested list
* // Return null if this NestedInteger holds a single integer
* public List<NestedInteger> getList();
* }
*/
class Solution{ //23ms
public NestedInteger deserialize(String s) {
Stack<NestedInteger> stack = new Stack<NestedInteger>();
String tokenNum = "";
for (char c : s.toCharArray()) {
switch (c) {
case '['://[代表一个list
stack.push(new NestedInteger());
break;
case ']'://list结尾
if (!tokenNum.equals(""))//前面token为数字
stack.peek().add(new NestedInteger(Integer.parseInt(tokenNum)));//将数字加入到本层list中
NestedInteger ni = stack.pop();//本层list结束
tokenNum = "";
if (!stack.isEmpty()) {//栈内有更高层次的list
stack.peek().add(ni);
} else {//栈为空,遍历到字符串结尾
return ni;
}
break;
case ',':
if (!tokenNum.equals("")) //将数字加入到本层list中
stack.peek().add(new NestedInteger(Integer.parseInt(tokenNum)));
tokenNum = "";
break;
default:
tokenNum += c;
}
}
if (!tokenNum.equals(""))//特殊case: 如果字符串只包含数字的情况
return new NestedInteger(Integer.parseInt(tokenNum));
return null;
}
}
③ 在discuss中看到的,使用数组实现栈。。。
class Solution {
public NestedInteger deserialize(String s) {
NestedInteger parent = new NestedInteger();
deserialize(s.toCharArray(), 0, parent);
return parent.getList().get(0);
}
private int deserialize(char[] schar, int i, NestedInteger parent) {
char c = schar[i++];
NestedInteger nestedInteger;
if (c == '[') {
nestedInteger = new NestedInteger();
if(schar[i] == ']') {
i++;
} else {
do {
i = deserialize(schar, i, nestedInteger);
} while(schar[i++] != ']');
}
} else {
boolean isNeg = false;
if (c == '-') {
isNeg = true;
c = schar[i++];
}
int num = c - '0';
for (; i < schar.length && (c = schar[i]) >= '0' && c <= '9'; i++) {
num = num * 10 + c - '0';
}
nestedInteger = new NestedInteger(isNeg ? -num : num);
}
parent.add(nestedInteger);
return i;
}
}
【注】NestedInteger类的简单实现。
class NestedInteger {
private List<NestedInteger> list;
private Integer integer;
public NestedInteger(List<NestedInteger> list){
this.list = list;
}
public void add(NestedInteger nestedInteger) {
if(this.list != null){
this.list.add(nestedInteger);
} else {
this.list = new ArrayList();
this.list.add(nestedInteger);
}
}
public void setInteger(int num) {
this.integer = num;
}
public NestedInteger(Integer integer){
this.integer = integer;
}
public NestedInteger() {
this.list = new ArrayList();
}
public boolean isInteger() {
return integer != null;
}
public Integer getInteger() {
return integer;
}
public List<NestedInteger> getList() {
return list;
}
public String printNi(NestedInteger thisNi, StringBuilder sb){
if(thisNi.isInteger()) {
sb.append(thisNi.integer);
sb.append(",");
}
sb.append("[");
for(NestedInteger ni : thisNi.list){
if(ni.isInteger()) {
sb.append(ni.integer);
sb.append(",");
}
else {
printNi(ni, sb);
}
}
sb.append("]");
return sb.toString();
}
}