Given a string s represents the serialization of a nested list, implement a parser to deserialize it and return the deserialized NestedInteger
.
Each element is either an integer or a list whose elements may also be integers or other lists.
Example 1:
Input: s = "324" Output: 324 Explanation: You should return a NestedInteger object which contains a single integer 324.
Example 2:
Input: s = "[123,[456,[789]]]" Output: [123,[456,[789]]] Explanation: 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
Constraints:
1 <= s.length <= 5 * 104
s
consists of digits, square brackets "[]"
, negative sign '-'
, and commas ','
.s
is the serialization of valid NestedInteger
.[-106, 106]
.This problem involves deserializing a string representing a nested list into a nested integer structure. Two approaches are presented: recursion and stack-based iteration. Both achieve a time complexity of O(n), where n is the length of the input string.
This approach leverages recursion to elegantly handle the nested structure. The core idea is to break down the problem into smaller subproblems.
Algorithm:
Base Cases:
s
is empty or represents an empty list ([]
), return an empty NestedInteger
.s
starts with a digit (not a '['), it represents a single integer; parse it and return a NestedInteger
containing that integer.Recursive Step:
[...]
). The algorithm iterates through the string:
,
) or the closing bracket (]
) is encountered while the depth is 0, it indicates the end of a NestedInteger
within the current list. A substring is extracted, representing this inner element, and the function recursively calls itself (deserialize()
) to parse this substring. The resulting NestedInteger
is added to the current list.[
) increment the depth, and closing brackets (]
) decrement it. This tracks the nesting levels.Time Complexity: O(n) - Each character is visited at most once during traversal and recursion.
Space Complexity: O(n) - The recursive call stack can have a depth proportional to the nesting level, and the nested list structure itself can also take O(n) space.
This approach uses a stack data structure to mimic the recursion process iteratively.
Algorithm:
Base Case: If the input string s
does not start with '[', it's a single integer; parse and return.
Iteration and Stack Management: The algorithm iterates through the input string:
neg
flag to handle negative numbers.x
variable.NestedInteger
onto the stack to represent a new nested list.x
(considering the neg
flag) is added to the top NestedInteger
on the stack. If it's ']', and the stack has more than one element, the top NestedInteger
is popped and added to the one below it, reflecting the nested structure.Time Complexity: O(n) - Similar to the recursive approach, each character is processed once.
Space Complexity: O(n) - The stack can grow to a size proportional to the maximum nesting depth of the list.
Approach 1 (Recursion):
class Solution:
def deserialize(self, s: str) -> NestedInteger:
if not s or s == '[]':
return NestedInteger()
if s[0] != '[':
return NestedInteger(int(s))
ans = NestedInteger()
depth, j = 0, 1
for i in range(1, len(s)):
if depth == 0 and (s[i] == ',' or i == len(s) - 1):
ans.add(self.deserialize(s[j:i]))
j = i + 1
elif s[i] == '[':
depth += 1
elif s[i] == ']':
depth -= 1
return ans
Approach 2 (Stack):
class Solution:
def deserialize(self, s: str) -> NestedInteger:
if s[0] != '[':
return NestedInteger(int(s))
stk, x, neg = [], 0, False
for i, c in enumerate(s):
if c == '-':
neg = True
elif c.isdigit():
x = x * 10 + int(c)
elif c == '[':
stk.append(NestedInteger())
elif c in ',]':
if s[i - 1].isdigit():
if neg:
x = -x
stk[-1].add(NestedInteger(x))
x, neg = 0, False
if c == ']' and len(stk) > 1:
t = stk.pop()
stk[-1].add(t)
return stk.pop()
The code examples in other languages (Java, C++, Go, TypeScript) would follow similar algorithmic structures, adapting syntax and data structures as needed for each language. The core concepts of recursion or stack-based iteration remain the same across all implementations.