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
NestedIntegertrongnestedList, ta sẽ gọi hàmflattenđể duyệt qua toàn bộNestedIntegervà lưu kết quả vàonums.
Ở hàm flatten:
- Tạo một mảng tạm
numsrỗng. - Nếu
nestedIntegerlà một số nguyên, ta sẽ thêm nó vàonums. - Nếu
nestedIntegerlà một list cácNestedInteger, ta sẽ gọi đệ quy hàmflattenvớinestedIntegernày. - Trả về
nums.
Ở hàm HasNext():
- Trả về
idx < len(nums).
Ở hàm Next():
- Tăng
idxlê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ộ
nestedListvàointernalStack.
Ở hàm unpack():
- Lặp chừng nào
internalStackkhông rỗng vàinternalStack.top()không phải số nguyên:- Lấy
topcủainternalStackra và gán vàonestedInteger. - Với từng
NestedIntegertrongnestedInteger.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
topcủainternalStackra. popinternalStack.- 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...)
}
}
}