给定一个字符串 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 * 104
s
由数字、方括号 "[]"
、负号 '-'
、逗号 ','
组成
用例保证 s
是可解析的 NestedInteger
输入中的所有值的范围是 [-106, 106]
方法一:深度优先搜索 思路
根据题意,一个 NestedInteger 实例只能包含下列两部分之一:1)一个整数;2)一个列表,列表中的每个元素都是一个 NestedInteger 实例。据此,NestedInteger 是通过递归定义的,因此也可以用递归的方式来解析。
从左至右遍历 $s$,
如果第一位是 [' 字符,则表示待解析的是一个列表,从
[‘ 后面的字符开始又是一个新的 NestedInteger 实例,我们仍调用解析函数来解析列表的元素,调用结束后如果遇到的是 $,$ 字符,表示列表仍有其他元素,需要继续调用。如果是 `]’ 字符,表示这个列表已经解析完毕,可以返回 NestedInteger 实例。
否则,则表示待解析的 NestedInteger 只包含一个整数。我们可以从左至右解析这个整数,并注意是否是负数,直到遍历完或者遇到非数字字符(]' 或
,’),并返回 NestedInteger 实例。
代码
[sol1-Python3] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 class Solution : def deserialize (self, s: str ) -> NestedInteger: index = 0 def dfs () -> NestedInteger: nonlocal index if s[index] == '[' : index += 1 ni = NestedInteger() while s[index] != ']' : ni.add(dfs()) if s[index] == ',' : index += 1 index += 1 return ni else : negative = False if s[index] == '-' : negative = True index += 1 num = 0 while index < len (s) and s[index].isdigit(): num *= 10 num += int (s[index]) index += 1 if negative: num = -num return NestedInteger(num) return dfs()
[sol1-Java] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 class Solution { int index = 0 ; public NestedInteger deserialize (String s) { if (s.charAt(index) == '[' ) { index++; NestedInteger ni = new NestedInteger (); while (s.charAt(index) != ']' ) { ni.add(deserialize(s)); if (s.charAt(index) == ',' ) { index++; } } index++; return ni; } else { boolean negative = false ; if (s.charAt(index) == '-' ) { negative = true ; index++; } int num = 0 ; while (index < s.length() && Character.isDigit(s.charAt(index))) { num = num * 10 + s.charAt(index) - '0' ; index++; } if (negative) { num *= -1 ; } return new NestedInteger (num); } } }
[sol1-C#] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 public class Solution { int index = 0 ; public NestedInteger Deserialize (string s ) { if (s[index] == '[' ) { index++; NestedInteger ni = new NestedInteger(); while (s[index] != ']' ) { ni.Add(Deserialize(s)); if (s[index] == ',' ) { index++; } } index++; return ni; } else { bool negative = false ; if (s[index] == '-' ) { negative = true ; index++; } int num = 0 ; while (index < s.Length && char .IsDigit(s[index])) { num = num * 10 + s[index] - '0' ; index++; } if (negative) { num *= -1 ; } return new NestedInteger(num); } } }
[sol1-C++] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 class Solution {public : int index = 0 ; NestedInteger deserialize (string s) { if (s[index] == '[' ) { index++; NestedInteger ni; while (s[index] != ']' ) { ni.add (deserialize (s)); if (s[index] == ',' ) { index++; } } index++; return ni; } else { bool negative = false ; if (s[index] == '-' ) { negative = true ; index++; } int num = 0 ; while (index < s.size () && isdigit (s[index])) { num = num * 10 + s[index] - '0' ; index++; } if (negative) { num *= -1 ; } return NestedInteger (num); } } };
[sol1-C] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 struct NestedInteger* helper (const char * s, int * index) { if (s[*index] == '[' ) { (*index)++; struct NestedInteger * ni = NestedIntegerInit(); while (s[*index] != ']' ) { NestedIntegerAdd(ni, helper(s, index)); if (s[*index] == ',' ) { (*index)++; } } (*index)++; return ni; } else { bool negative = false ; if (s[*index] == '-' ) { negative = true ; (*index)++; } int num = 0 ; while (s[*index] && isdigit (s[*index])) { num = num * 10 + s[*index] - '0' ; (*index)++; } if (negative) { num *= -1 ; } struct NestedInteger * ni = NestedIntegerInit(); NestedIntegerSetInteger(ni, num); return ni; } } struct NestedInteger* deserialize (char * s) { int index = 0 ; return helper(s, &index); }
[sol1-JavaScript] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 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 ; }
[sol1-Golang] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 func deserialize (s string ) *NestedInteger { index := 0 var dfs func () *NestedInteger dfs = func () *NestedInteger { ni := &NestedInteger{} if s[index] == '[' { index++ for s[index] != ']' { ni.Add(*dfs()) if s[index] == ',' { index++ } } index++ return ni } negative := s[index] == '-' if negative { index++ } num := 0 for ; index < len (s) && unicode.IsDigit(rune (s[index])); index++ { num = num*10 + int (s[index]-'0' ) } if negative { num = -num } ni.SetInteger(num) return ni } return dfs() }
复杂度分析
方法二:栈 思路
上述递归的思路也可以用栈来模拟。从左至右遍历 $s$,如果遇到 [',则表示是一个新的 NestedInteger 实例,需要将其入栈。如果遇到
]’ 或 `,’,则表示是一个数字或者 NestedInteger 实例的结束,需要将其添加入栈顶的 NestedInteger 实例。最后需返回栈顶的实例。
代码
[sol2-Python3] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 class Solution : def deserialize (self, s: str ) -> NestedInteger: if s[0 ] != '[' : return NestedInteger(int (s)) stack, num, negative = [], 0 , False for i, c in enumerate (s): if c == '-' : negative = True elif c.isdigit(): num = num * 10 + int (c) elif c == '[' : stack.append(NestedInteger()) elif c in ',]' : if s[i-1 ].isdigit(): if negative: num = -num stack[-1 ].add(NestedInteger(num)) num, negative = 0 , False if c == ']' and len (stack) > 1 : stack[-2 ].add(stack.pop()) return stack.pop()
[sol2-Java] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 class Solution { public NestedInteger deserialize (String s) { if (s.charAt(0 ) != '[' ) { return new NestedInteger (Integer.parseInt(s)); } Deque<NestedInteger> stack = new ArrayDeque <NestedInteger>(); int num = 0 ; boolean negative = false ; for (int i = 0 ; i < s.length(); i++) { char c = s.charAt(i); if (c == '-' ) { negative = true ; } else if (Character.isDigit(c)) { num = num * 10 + c - '0' ; } else if (c == '[' ) { stack.push(new NestedInteger ()); } else if (c == ',' || c == ']' ) { if (Character.isDigit(s.charAt(i - 1 ))) { if (negative) { num *= -1 ; } stack.peek().add(new NestedInteger (num)); } num = 0 ; negative = false ; if (c == ']' && stack.size() > 1 ) { NestedInteger ni = stack.pop(); stack.peek().add(ni); } } } return stack.pop(); } }
[sol2-C#] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 public class Solution { public NestedInteger Deserialize (string s ) { if (s[0 ] != '[' ) { return new NestedInteger(int .Parse(s)); } Stack<NestedInteger> stack = new Stack<NestedInteger>(); int num = 0 ; bool negative = false ; for (int i = 0 ; i < s.Length; i++) { char c = s[i]; if (c == '-' ) { negative = true ; } else if (char .IsDigit(c)) { num = num * 10 + c - '0' ; } else if (c == '[' ) { stack.Push(new NestedInteger()); } else if (c == ',' || c == ']' ) { if (char .IsDigit(s[i - 1 ])) { if (negative) { num *= -1 ; } stack.Peek().Add(new NestedInteger(num)); } num = 0 ; negative = false ; if (c == ']' && stack.Count > 1 ) { NestedInteger ni = stack.Pop(); stack.Peek().Add(ni); } } } return stack.Pop(); } }
[sol2-C++] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 class Solution {public : NestedInteger deserialize (string s) { if (s[0 ] != '[' ) { return NestedInteger (stoi (s)); } stack<NestedInteger> st; int num = 0 ; bool negative = false ; for (int i = 0 ; i < s.size (); i++) { char c = s[i]; if (c == '-' ) { negative = true ; } else if (isdigit (c)) { num = num * 10 + c - '0' ; } else if (c == '[' ) { st.emplace (NestedInteger ()); } else if (c == ',' || c == ']' ) { if (isdigit (s[i - 1 ])) { if (negative) { num *= -1 ; } st.top ().add (NestedInteger (num)); } num = 0 ; negative = false ; if (c == ']' && st.size () > 1 ) { NestedInteger ni = st.top (); st.pop (); st.top ().add (ni); } } } return st.top (); } };
[sol2-C] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 #define MAX_NEST_LEVEL 50001 struct NestedInteger* deserialize (char * s) { if (s[0 ] != '[' ) { struct NestedInteger * ni = NestedIntegerInit(); NestedIntegerSetInteger(ni, atoi(s)); return ni; } struct NestedInteger **stack = (struct NestedInteger **)malloc (sizeof (struct NestedInteger *) * MAX_NEST_LEVEL); int top = 0 ; int num = 0 ; bool negative = false ; int n = strlen (s); for (int i = 0 ; i < n; i++) { char c = s[i]; if (c == '-' ) { negative = true ; } else if (isdigit (c)) { num = num * 10 + c - '0' ; } else if (c == '[' ) { struct NestedInteger * ni = NestedIntegerInit(); stack [top++] = ni; } else if (c == ',' || c == ']' ) { if (isdigit (s[i - 1 ])) { if (negative) { num *= -1 ; } struct NestedInteger * ni = NestedIntegerInit(); NestedIntegerSetInteger(ni, num); NestedIntegerAdd(stack [top - 1 ], ni); } num = 0 ; negative = false ; if (c == ']' && top > 1 ) { struct NestedInteger *ni = stack [top - 1 ]; top--; NestedIntegerAdd(stack [top - 1 ], ni); } } } struct NestedInteger * res = stack [top - 1 ]; free (stack ); return res; }
[sol2-JavaScript] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 var deserialize = function (s ) { if (s[0 ] !== '[' ) { return new NestedInteger (parseInt (s)); } const stack = []; let num = 0 ; let negative = false ; for (let i = 0 ; i < s.length ; i++) { const c = s[i]; if (c === '-' ) { negative = true ; } else if (isDigit (c)) { num = num * 10 + c.charCodeAt () - '0' .charCodeAt (); } else if (c === '[' ) { stack.push (new NestedInteger ()); } else if (c === ',' || c === ']' ) { if (isDigit (s[i - 1 ])) { if (negative) { num *= -1 ; } stack[stack.length - 1 ].add (new NestedInteger (num)); } num = 0 ; negative = false ; if (c === ']' && stack.length > 1 ) { const ni = stack.pop (); stack[stack.length - 1 ].add (ni); } } } return stack.pop (); }; const isDigit = (ch ) => { return parseFloat (ch).toString () === "NaN" ? false : true ; }
[sol2-Golang] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 func deserialize (s string ) *NestedInteger { if s[0 ] != '[' { num, _ := strconv.Atoi(s) ni := &NestedInteger{} ni.SetInteger(num) return ni } stack, num, negative := []*NestedInteger{}, 0 , false for i, ch := range s { if ch == '-' { negative = true } else if unicode.IsDigit(ch) { num = num*10 + int (ch-'0' ) } else if ch == '[' { stack = append (stack, &NestedInteger{}) } else if ch == ',' || ch == ']' { if unicode.IsDigit(rune (s[i-1 ])) { if negative { num = -num } ni := NestedInteger{} ni.SetInteger(num) stack[len (stack)-1 ].Add(ni) } num, negative = 0 , false if ch == ']' && len (stack) > 1 { stack[len (stack)-2 ].Add(*stack[len (stack)-1 ]) stack = stack[:len (stack)-1 ] } } } return stack[len (stack)-1 ] }
复杂度分析