Bài toán
Link đến bài toán: 341. Flatten Nested List Iterator
Phân tích
Đề bài yeu cầu ta implement một iterator
cho một list các NestedInteger
,
mỗi NestedInteger
có thể là một số nguyên hoặc một list các NestedInteger
khác.
Có 2 hướng giải quyết bài toán này: “lazy” và “eager”.
Đối với hướng “eager”, tại thời điểm khởi tạo iterator
, ta dùng đệ quy để duyệt qua toàn bộ NestedInteger
và lưu lại kết quả vào một mảng.
Đối với hướng “lazy”, ta sẽ xử lý từng NestedInteger
khi cần thiết (cụ thể là khi hàm HasNext()
và Next()
được gọi).
Giải thuật
Eager
Kiểu Iterator của ta sẽ chứa một mảng nums
và một biến idx
để lưu vị trí hiện tại.
Ở constructor:
- Với mỗi
NestedInteger
trongnestedList
, ta sẽ gọi hàmflatten
để duyệt qua toàn bộNestedInteger
và lưu kết quả vàonums
.
Ở hàm flatten
:
- Tạo một mảng tạm
nums
rỗng. - Nếu
nestedInteger
là một số nguyên, ta sẽ thêm nó vàonums
. - Nếu
nestedInteger
là một list cácNestedInteger
, ta sẽ gọi đệ quy hàmflatten
vớinestedInteger
này. - Trả về
nums
.
Ở hàm HasNext()
:
- Trả về
idx < len(nums)
.
Ở hàm Next()
:
- Tăng
idx
lên 1. - Trả về
nums[idx-1]
.
Độ phức tạp: O(n)
Độ phức tạp không gian: O(n)
Lazy
Kiểu Iterator của ta sẽ chứa một stack internalStack
.
Ở constructor:
- Đưa toàn bộ
nestedList
vàointernalStack
.
Ở hàm unpack()
:
- Lặp chừng nào
internalStack
không rỗng vàinternalStack.top()
không phải số nguyên:- Lấy
top
củainternalStack
ra và gán vàonestedInteger
. - Với từng
NestedInteger
trongnestedInteger.getList()
, ta đẩy nó vào đầu stack.
- Lấy
Ở hàm HasNext()
:
- Gọi hàm
unpack()
. - Trả về
len(internalStack) > 0
.
Ở hàm Next()
:
- Gọi hàm
unpack()
. - Lấy
top
củainternalStack
ra. pop
internalStack
.- Trả về
top
.
Độ phức tạp: O(n)
Độ phức tạp không gian: Nhỏ hơn O(n)
do ta không cần lưu toàn bộ nestedList
vào internalStack
.
type NestedIterator struct {
internalStack []*NestedInteger
}
func Constructor(nestedList []*NestedInteger) NestedIterator {
return NestedIterator{
internalStack: nestedList,
}
}
func (this *NestedIterator) Next() int {
this.unpack()
top := this.internalStack[0]
this.internalStack = this.internalStack[1:]
return top.GetInteger()
}
func (this *NestedIterator) HasNext() bool {
this.unpack()
return len(this.internalStack) > 0
}
func (this *NestedIterator) unpack() {
for len(this.internalStack) > 0 {
top := this.internalStack[0]
if top.IsInteger() {
break
}
this.internalStack = this.internalStack[1:]
list := top.GetList()
for i := len(list) - 1; i >= 0; i-- {
this.internalStack = append([]*NestedInteger{list[i]}, this.internalStack...)
}
}
}