题目
难度:★★★☆☆
类型:数组
方法:动态规划
给你一个嵌套的整型列表。请你设计一个迭代器,使其能够遍历这个整型列表中的所有整数。
列表中的每一项或者为一个整数,或者是另一个列表。其中列表的元素也可能是整数或是其他列表。
示例
示例 1:
输入: [[1,1],2,[1,1]]
输出: [1,1,2,1,1]
解释: 通过重复调用 next 直到 hasNext 返回 false,next 返回的元素的顺序应该是: [1,1,2,1,1]。
示例 2:
输入: [1,[4,[6]]]
输出: [1,4,6]
解释: 通过重复调用 next 直到 hasNext 返回 false,next 返回的元素的顺序应该是: [1,4,6]。
解答
首先,有必要给出这个嵌套列表跟我们平常所用的有什么不同,需要给出详细的构造代码。首先是结点,结点的值可以是整数也可以是列表,具有获取整数和获取列表两个方法。
class NestedInteger:
def __init__(self, value):
self.value = value
def isInteger(self) -> bool:
"""
@return True if this NestedInteger holds a single integer, rather than a nested list.
"""
return isinstance(self.value, int)
def getInteger(self) -> int:
"""
@return the single integer that this NestedInteger holds, if it holds a single integer
Return None if this NestedInteger holds a nested list
"""
assert isinstance(self.value, int)
return self.value
def getList(self):
"""
@return the nested list that this NestedInteger holds, if it holds a nested list
Return None if this NestedInteger holds a single integer
"""
assert isinstance(self.value, list)
return self.value
然后是构造嵌套列表,这里使用深度优先搜索实现:
def create_nested_list(l):
"""
构造一个嵌套列表。
:param l:
:return:
"""
res_lst = []
for item in l:
if isinstance(item, int):
res_lst.append(NestedInteger(item))
elif isinstance(item, list):
res_lst.append(create_nested_list(item))
return NestedInteger(res_lst)
我们用类似的方法实现嵌套链表的解压,和构造过程是逆过程。
def flatten_nested_list(lst):
"""
将嵌套列表扁平化。
:param lst:
:return:
"""
res = []
def dfs(l):
if isinstance(l, NestedInteger):
l = l.getInteger() if l.isInteger() else l.getList()
for item in l:
assert isinstance(item, NestedInteger)
if item.isInteger():
res.append(item.getInteger())
else:
dfs(item.getList())
dfs(lst)
return res
然后就可以解决问题了。
方法1:直接解压嵌套列表
将嵌套列表解压,用指针来标记当前位置。这个思路很简洁。
class NestedIterator:
"""
嵌套列表迭代器
"""
def __init__(self, nestedList):
self.flat_list = flatten_nested_list(nestedList)
self.point = 0
self.length = len(self.flat_list)
def next(self) -> int:
self.point += 1
return self.flat_list[self.point-1]
def hasNext(self) -> bool:
return self.point < self.length
方法2:堆栈
参考大佬解决方案。
class NestedIterator:
def __init__(self, nestedList: [NestedInteger]):
# 对于nestedList中的内容,我们需要从左往右遍历,
# 但堆栈pop是从右端开始,所以我们压栈的时候需要将nestedList反转再压栈
self.stack = nestedList[::-1]
def next(self) -> int:
# hasNext 函数中已经保证栈顶是integer,所以直接返回pop结果
return self.stack.pop(-1).getInteger()
def hasNext(self) -> bool:
# 对栈顶进行‘剥皮’,如果栈顶是List,把List反转再依次压栈,
# 然后再看栈顶,依次循环直到栈顶为Integer。
# 同时可以处理空的List,类似[[[]],[]]这种test case
while len(self.stack) > 0 and self.stack[-1].isInteger() is False:
self.stack += self.stack.pop().getList()[::-1]
return len(self.stack) > 0
方法3:生成器
充分利用python的作用,用生成器构造。
class NestedIterator(object):
def __init__(self, nestedList):
"""
Initialize your data structure here.
:type nestedList: List[NestedInteger]
"""
def build_generator(nestedList):
for i in nestedList:
if i.isInteger():
yield i.getInteger()
else:
i = i.getList()
for j in build_generator(i):
yield j
self.g = build_generator(nestedList)
def next(self):
"""
:rtype: int
"""
#print(self.v)
return self.v
def hasNext(self):
"""
:rtype: bool
"""
try:
self.v = next(self.g)
#print(self.v)
return True
except:
return False
整体代码
以方法1为例,大家可以把下面的代码段粘贴运行,熟悉整个工作流程。
def create_nested_list(l):
"""
构造一个嵌套列表。
:param l:
:return:
"""
res_lst = []
for item in l:
if isinstance(item, int):
res_lst.append(NestedInteger(item))
elif isinstance(item, list):
res_lst.append(create_nested_list(item))
return NestedInteger(res_lst)
def flatten_nested_list(lst):
"""
将嵌套列表扁平化。
:param lst:
:return:
"""
res = []
def dfs(l):
if isinstance(l, NestedInteger):
l = l.getInteger() if l.isInteger() else l.getList()
for item in l:
assert isinstance(item, NestedInteger)
if item.isInteger():
res.append(item.getInteger())
else:
dfs(item.getList())
dfs(lst)
return res
class NestedInteger:
def __init__(self, value):
self.value = value
def isInteger(self) -> bool:
"""
@return True if this NestedInteger holds a single integer, rather than a nested list.
"""
return isinstance(self.value, int)
def getInteger(self) -> int:
"""
@return the single integer that this NestedInteger holds, if it holds a single integer
Return None if this NestedInteger holds a nested list
"""
assert isinstance(self.value, int)
return self.value
def getList(self):
"""
@return the nested list that this NestedInteger holds, if it holds a nested list
Return None if this NestedInteger holds a single integer
"""
assert isinstance(self.value, list)
return self.value
class NestedIterator:
"""
嵌套列表迭代器
"""
def __init__(self, nestedList):
self.flat_list = flatten_nested_list(nestedList)
self.point = 0
self.length = len(self.flat_list)
def next(self) -> int:
self.point += 1
return self.flat_list[self.point-1]
def hasNext(self) -> bool:
return self.point < self.length
if __name__ == "__main__":
nestedList = [[1,1],2,[1,1]]
nestedList = create_nested_list(nestedList).value
# print(flatten_nested_list(nestedList))
i, v = NestedIterator(nestedList), []
while i.hasNext():
v.append(i.next())
print(v)
如有疑问或建议,欢迎评论区留言~