KK's blog

每天积累多一些

0%

算法思路:

  1. 循环条件start + 1 < end。 当跳出循环时,start和end的关系只能是相等或相邻。
    相等是若数组只有一个元素,没有进入循环时出现。当进入过循环,一定是相邻。
  2. 跳出循环后比较start和end的关系从而判断答案。

这可以满足二分法找first position或者last position, peak element的题目。
first position中若等于target,end = mid,因为要在左半部分找,相反last
position在右半部分找,所以start = mid。

应用:

  1. 有序数组找目标
  2. 没给定目标情况下,找峰值, 缺失数(元素间关系)
  3. 没给定目标情况下,求第k小的数,如求根号(数值关系)

找目标

注意事项:

  1. 判断数组是否为空。
  2. 如果只有唯一的target的话,target==nums[mid]可以并入任何一种。end和target的顺序也没关系。其他注意循环后要根据题目条件(如小于或者大于或者等于tgt),
    再比较一次start和end上的元素,详见下表
  3. start + (end - start) // 2 是// 2
类型 if target = nums[mid] 循环之后 备注
binary_search 任意 任意 N/A
last_position 向右start = mid 先end且是否等于tgt 贪婪法,找最后一个target,所以尽量靠后,先end
first_position 向左end = mid 先start是否等于tgt 贪婪法,找第一个target,所以尽量靠前,先start
smaller(_or_equal)_position 向左end = mid 先end是否小于tgt 贪婪法,找最后一个小于target的数,所以尽量靠近target,先end
greater(_or_equal)_position 向右start = mid 先start是否大于tgt 贪婪法,找第一个大于target的数,所以尽量靠近target,先start

Python代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
def binary_search(self, nums: List[int], target: int) -> int:
if not nums:
return -1
start, end = 0, len(nums) - 1
while start + 1 < end:
mid = start + (end - start) // 2
if target < nums[mid]:
end = mid
else:
start = mid

if nums[end] == target:
return end
elif nums[start] == target:
return start
else:
return -1

Python代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
def last_position(self, nums: List[int], target: int) -> int:
if not nums:
return -1
start, end = 0, len(nums) - 1
while start + 1 < end:
mid = start + (end - start) // 2
if target < nums[mid]:
end = mid
elif target > nums[mid]:
start = mid
else: # Depends on the target on the right side or left side. For fist pos, use end = mid
start = mid

if nums[end] == target:
return end
elif nums[start] == target:
return start
else:
return -1

Python代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
def first_position(self, nums: List[int], target: int) -> int:
if not nums:
return -1
start, end = 0, len(nums) - 1
while start + 1 < end:
mid = start + (end - start) // 2
if target < nums[mid]:
end = mid
elif target > nums[mid]:
start = mid
else:
end = mid

if nums[start] == target:
return start
elif nums[end] == target:
return end
else:
return -1

Python代码:

如果是smaller_or_equal_position,Line 13和15取等号

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
def smaller_position(self, nums: List[int], target: int) -> int:
if not nums:
return -1
start, end = 0, len(nums) - 1
while start + 1 < end:
mid = start + (end - start) // 2
if target > nums[mid]:
start = mid
elif target < nums[mid]:
end = mid
else:
end = mid
if nums[end] < target: # nums[end] <= target for smaller_or_equal_position
return end
if nums[start] < target: # nums[start] < target for smaller_or_equal_position
return start
return -1

Python代码:

如果是greater_or_equal_position,Line 13和15取等号

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
def greater_position(self, nums: List[int], target: int) -> int:
if not nums:
return -1
start, end = 0, len(nums) - 1
while start + 1 < end:
mid = start + (end - start) // 2
if target > nums[mid]:
start = mid
elif target < nums[mid]:
end = mid
else:
start = mid
if nums[start] > target: # nums[start] >= target for greater_or_equal_position
return start
if nums[end] > target: # nums[end] >= target for greater_or_equal_position
return end
return -1

找峰值

注意事项:

  1. 判断mid+1的元素不越界
  2. 最后返回start和end之中较大者

Python代码:

1
2
3
4
5
6
7
8
9
10
11
def find_peak(self, nums: List[int]) -> int:
if not nums:
return -1
start, end = 0, len(nums) - 1
while start + 1 < end:
mid = start + (end - start) // 2
if mid + 1 <= end and nums[mid] < nums[mid + 1]:
start = mid
else:
end = mid
return start if nums[start] > nums[end] else end

数值二分法 - 找第k小的数

模板类似于标准二分法模板,区别是start和end取值以及epsilon取值是0.5而不是1

Python代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
def minEatingSpeed(self, piles: List[int], target: int) -> int:
def f(piles, k):
return <按照题目要求>

start, end = <数值最小值>, <数值最小值>
while start + 0.5 < end:
mid = start + (end - start) / 2
res = f(piles, mid)
if <target与res的关系,需要在某一个条件取等号,以为是数值二分法>:
end = mid
else:
start = mid
return int(end)

注意事项:

  1. 思考数组范围(代码连续3行都是注意事项)
  2. epsilon取0.5. 一般整数题都取0.5
  3. mid是除2获得不是//2
  4. 模板中target和res取等号时,不能return,要继续在某半区找,因为要达到误差epsilon内才会停止。类似于first_position或者last_position

Python代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import math
def binary_select(self, nums: List[int], k: int) -> int:
if not nums:
return -1
start, end, epsilon = min(nums), max(nums), 0.5
while end - start > epsilon:
mid = start + (end - start) / 2
count = len([n for n in nums if n <= mid])
if k < count:
end = mid
elif k > count:
start = mid
else:
start = mid
return int(end)
若nums有序,count的统计可以用bisect(nums, mid)完成,记得不需要用+1,而且空数组也无问题
上面line 8可以改成
1
count = bisect.bisect(matrix[i], mid)

注意事项:

  1. 数值比较,所以mid是除2获得不是//2。start,end,mid都是数值而不是索引
  2. k是从0开始,count==k的时候,k在mid的右边,如数组1-10, k=3, mid=3.5, count=3,k是前4个数,所以在mid右边。nums[i] <= mid这个等号有没有也没关系,因为mid是小数,不会相等的。
  3. 最后start,end区间内是一个整数正是所求,所以返回end向下取整

算法分析:

时间复杂度为O(nlog(|hi-lo|/epsilon)),如果数据比较平均也就是差值相当的情况下(比如1,2,3),复杂度为O(nlogn). 空间复杂度O(1)。 若不需要搜索全数组,前面的n会变成logn

例子:

LeetCode 875 Koko Eating Bananas

Python代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
def minEatingSpeed(self, piles: List[int], h: int) -> int:
#if len(piles) == 1: # attn
# return math.ceil(piles[0] / h)
# piles.sort()

def get_hours(piles, k):
return sum([math.ceil(n / k) for n in piles])


# start, end = piles[0], piles[-1] # 3, 4
start, end = 1, max(piles) # attn: 1 rather than min(piles)
while start + 0.5 < end: # attn: use 0.5
mid = start + (end - start) / 2 # attn /2 not // 2 | 7, 5, 4
hours = get_hours(piles, int(mid)) # attn: int(mid) | 5, 8, 8
if h >= hours: # eat slower, attn 8 > 5
end = mid # end=7, 5, 4
else:
start = mid

注意事项:

  1. start是从1开始,不是min(piles)。最大值取max(piles)因为跟取整型最大值是一样的。这样也可以避免单独处理单元素数组。
  2. epsilon取0.5. 一般整数题都取0.5
  3. mid是除2获得不是//2
  4. mid作为参数输入到get_hours()要去int(mid)与题目一致,因为题目的k是整数
  5. 模板中h==hours时,不能return,要继续在左半区找,因为要达到误差epsilon内才会停止。类似于first_position

中序遍历算法思路:

如图所示,总体思路是左节点按层次遍历,而区别在于何时加入到结果集。

  1. 首先初始化将root的所有左儿子加入到stack。
  2. 开始循环,取出节点,判断其右儿子不为空,因为左儿子已经访问过。
  3. 若右子树不为空,跟初始化一样,将右子树的所有左儿子加入到栈中。
  4. 用到两个指针node和n,分别指向出栈节点和遍历所有左儿子节点。

若前序遍历,只要把打印语句从出栈时打印移到入栈时打印即可。见L144

应用:

  1. BST的关于Iterator的题目Leetcode 173
  2. 不需要遍历所有节点而需要遍历某些节点的题目如求某target最接近N个节点。Leetcode 272

中序遍历

Leetcode 094 Binary Tree Inorder Traversal

Python代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
def iterative_inorder(self, root: TreeNode) -> List[int]:
if not root:
return []
res, stack = [], []
it = root
while it:
stack.append(it)
it = it.left
while stack:
node = stack.pop()
res.append(node.val)
if node.right:
n = node.right
while n:
stack.append(n)
n = n.left
return res

前序遍历

Leetcode 144 Binary Tree Preorder Traversal
只要将出栈节点加入结果换到入栈前加即可,也就是将Line 11换到取Line 7和Line 15

Python代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
def iterative_preorder(self, root: TreeNode) -> List[int]:
if not root:
return []
res, stack = [], []
it = root
while it:
stack.append(it)
res.append(it.val)
it = it.left
while stack:
node = stack.pop()
if node.right:
n = node.right
while n:
stack.append(n)
res.append(n.val)
n = n.left
return res

后序遍历

Leetcode 145 Binary Tree Postorder Traversal
跟中序比,需要用一个记数器来记录出现在栈顶的次数,若为2次就加入到结果集,并且不能继续迭代到右节点,因为第一次时候已做了。
由于tuple不可改,所以即使次数为1,也要出栈,更新次数后重新入栈。代码区别在Line 10 - 17.

注意事项:

  1. 记得要continue。
  2. 每个node出栈后再次入栈(else里面)

Python代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
def iterative_postorder(self, root: TreeNode) -> List[int]:
if not root:
return []
it = root
stack, res, freq = [], [], defaultdict(int)
while it:
stack.append(it)
it = it.left
while stack:
node = stack.pop()
freq[node] += 1
if freq[node] == 2:
res.append(node.val)
continue
else:
stack.append(node)
if node.right:
n = node.right
while n:
stack.append(n)
n = n.left
return res

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
def iterative_postorder(self, root: TreeNode) -> List[int]:
if not root:
return []
res, stack = [], []
it = root
while it:
stack.append((it, 0)) # count for it in the stack top
it = it.left
while stack:
pair = stack.pop()
node = pair[0]
occurrence = pair[1] + 1
if occurrence == 2:
res.append(node.val)
continue # don't iterate on right node again
else:
stack.append((node, occurrence))
if node.right:
n = node.right
while n:
stack.append((n, 0))
n = n.left
return res

递归写法

DFS BST的递归前序遍历Leetcode 0144 BST的递归中序遍历Leetcode 0094

Python代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
def recursive_inorder(self, root: TreeNode) -> List[int]:
return self.dfs_inorder(root)

def dfs_inorder(self, root):
if not root:
return []
return self.dfs_inorder(root.left) + [root.val] + self.dfs_inorder(root.right)

def recursive_preorder(self, root: TreeNode) -> List[int]:
return self.recursive_preorder(root)

def recursive_preorder(self, root):
if not root:
return []
return [root.val] + self.recursive_preorder(root.left) + self.recursive_preorder(root.right)

def recursive_postorder(self, root: TreeNode) -> List[int]:
return self.recursive_postorder(root)

def recursive_postorder(self, root):
if not root:
return []
return self.recursive_postorder(root.left) + self.recursive_postorder(root.right) + [root.val]

Java代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
protected void iterativeInorder(BinaryNode p) {  
Stack<BinaryNode> stack = new Stack<BinaryNode>();
BinaryNode head = p;
while(head != null) {
stack.push(head);
head = head.left;
}

BinaryNode node = null;
while (stack.size() > 0) {
node = stack.pop();
System.out.print(node.data);
if(node.right != null) {
BinaryNode n = node.right;
while(n != null) {
stack.push(n);
n = n.left;
}
}
}
}

算法分析:

时间复杂度为O(n),n为字符串长度,空间复杂度O(logn),最差为O(n)

算法思路:

Leetcode 078的题目。这里作为知识点归纳。

  1. 递归中i=st开始。
  2. 回溯: path递归后去恢复状态。
  3. dfs中传入i+1。
  4. 结果要复制new ArrayList<>(path)
  5. 一般来说,终止条件才加入结果,但由于子集任何path修改都是子集,所有立即加入。

和全排列的区别:

  1. 由于排列可以乱序如[1,2,3]结果是[1,3,2]也就是一个结果需要多次从左向右完全扫描,所以i=0开始且维护visited数组
    组合的结果是按照数组顺序的,所以只要从左到右扫描一次即可,所以用i=st。
  2. 结果方面,排列结果是满长度,而组合不是。所以在加入到res位置上,组合用st来判断是否结束且加入到path就立刻进入最后
    结果,而排列是在终结条件上加入。

注意事项:

  1. 输入不合法,返回[[]]
  2. 记得API是dfs(nums, st, path, result), 4个参数
  3. 递归是i+1,不是start+1

学习要点:

详见DFS要点,大部分DFS题目涉及

  1. 用到全组合的API: dfs(nums, start, path, result), 4个参数
  2. 用到全组合的递归: dfs(nums, i + 1, path, result)
  3. 用到全排列的其他部分包括恢复状态和终止条件(加入res)

应用:

  1. 找所有可能性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
def combine(self, nums: List[int]) -> List[List[int]]:
if not nums:
return [[]]
path, result = [], []
self.dfs(nums, 0, path, result)
return result

def dfs(self, nums, st, path, result):
if len(path) == len(nums):
return

for i in range(st, len(nums)):
path.append(nums[i])
result.append(list(path))
self.dfs(nums, i + 1, path, result)
path.pop()

Java代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public List<List<Integer>> subsets(int[] nums) {
List<Integer> path = new ArrayList<>();
List<List<Integer>> res = new ArrayList<>();
res.add(new ArrayList<>(path)); //empty set
if(nums == null || nums.length == 0)
return res;
dfs(nums, 0, path, res);
return res;
}

void dfs(int[] nums, int st, List<Integer> path, List<List<Integer>> res) {
if(st == nums.length)
return;

for(int i = st; i < nums.length; i++) {
path.add(nums[i]);
res.add(new ArrayList<>(path));
dfs(nums, i + 1, path, res);
path.remove(path.size() - 1);
}
}

算法分析:

时间复杂度为<code>O(2<sup>n</sup>)</code> ,空间复杂度O(1)

算法思路:

图用邻接表为输入,思路递归实现, 还要一个机制记录节点访问过没有,可以用HashSet,同时它作为结果存储BFS访问结果。
BFS多用于找最短路径 DFS多用于快速发现底部节点和具体路劲问题(如路径和或打印路径)。

BFS优缺点: 同一层的所有节点都会加入队列,所以耗用大量空间 仅能非递归实现 相比DFS较快,空间换时间 适合广度大的图

DFS优缺点: 无论是系统栈还是用户栈保存的节点数都只是树的深度,所以空间耗用小 有递归和非递归实现 由于有大量栈操作(特别是递归实现时候的系统调用),执行速度较BFS慢 适合深度大的图

如果BFS和DFS都可以用,建议用BFS,因为工业应用中,BFS不用有限的栈空间,可以利用到所有内存。

图DFS

算法步骤:

  1. 不合法情况(已访问、越界、trivial情况等)返回。
  2. 标记为已访问。
  3. 递归访问相邻节点。
  4. DFS路径尽量记录在数组中而非ArrayList中,路径(图)再DFS后要恢复为原状态L332。

Python代码:

1
2
3
4
5
6
7
def dfs(self, graph, start, visited, res):
if start in visited:
return
visited.add(start)
res.append(start)
for node in graph[start]:
self.dfs(graph, visited, node, res)

字符型DFS/组合

跟填位法相同的地方:

  1. 终止条件一样len(path)==TARGET, res.append(list(path)), return
  2. API一样:dfs(nums, start, path, result, visited[optional]), 4个参数 不同的是,组合模板是的下一轮递归用i + 1, 但这里由于是填位,一位一位加入,所以是start + 1

注意事项:

  1. 输入值为空的情况或空节点
  2. 求得解以后复制path到result中
  3. 终止条件记得return
  4. 每次递归完恢复输入图或中间结果path的状态,递归式用i + 1

Python代码:

1
2
3
4
5
6
7
8
def dfs(self, input, start, TARGET, path, result): 
if len(path) == TARGET:
result.append(list(path))
return
for i in <func>(input[start]):
path.append(i)
self.dfs(input, i + 1, TARGET , path, result)
path.pop()

例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# char dfs (type 2 linear) Leetcode 77 Given two integers n and k, return all possible combinations of k numbers out of the range [1, n]
def combine(self, n: int, k: int) -> List[List[int]]:
nums = [i + 1 for i in range(n)]
path, res = [], []
self.dfs2(nums, 0, k, [], res)
return res

def dfs2(self, nums, start, k, path, res):
if len(path) == k:
res.append(list(path))
return
for i in range(start, len(nums)):
path.append(nums[i])
self.dfs2(nums, i + 1, k, path, res)
path.pop()
另一个例子:LeetCode 093 Restore IP Addresses

填位法

跟字符型DFS/组合相同的地方:

  1. 终止条件一样len(path)==TARGET, res.append(list(path)), return
  2. API一样:dfs(nums, start, path, result, visited[optional]), 4个参数 不同的是,组合模板是的下一轮递归用i + 1, 但这里由于是填位,一位一位加入,所以是start + 1

Python代码:

1
2
3
4
5
6
7
8
9
10
11
12
def dfs(self, n, start, path, res, col_set):
if len(path) == TARGET:
res.append(list(path))
return
for i in range(n):
if not self.is_valid(start, i, col_set):
continue
path.append(i)
col_set.add(i)
self.dfs(n, start + 1, path, res, col_set)
col_set.remove(i)
path.pop()

例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# filling dfs (type 3) LeetCode 017 Letter Combinations of a Phone Number 
def letterCombinations(self, digits: str) -> List[str]:
if not digits:
return []
path, res = [], []
self.dfs3(digits, 0, path, res)
return res

def dfs3(self, digits, start, path, res):
if len(path) == len(digits): # len(path) == TARGET
res.append("".join(path))
return
keys = DIGIT2CHAR[digits[start]]
for letter in keys:
path.append(letter)
self.dfs3(digits, start + 1, path, res) # remember start + 1
path.pop()

Catalan法(双边递归)

DFS中几乎是最难的类型。考得很少。主要思想是左右儿子递归结果叉乘,再将所有结果返回。所以返回值一定是list

注意事项:

  1. 返回结果是解的集合,所以终止条件返回也需要是一个list
  2. 循环中除掉自己,递归左部分和右半部分,叉乘它们的结果
  3. 与记忆性搜索的模板类似,有时需要和它一起用,见LeetCode 241 Different Ways to Add Parentheses

Python代码:

1
2
3
4
5
6
7
8
9
def dfs(self, input):
if <终止条件>:
return [] # remember to use list
res = []
for i in range(len(input)):
left_res = self.dfs(input[:i])
right_res = self.dfs(input[i + 1:])
res += [<calculate results> for _l in left_res for _r in right_res]
return res

时间复杂度Catalan数为O(C[n] += C[i-1]*C[n-i]),空间复杂度O(1)

记忆性搜索(单边Catalan)

见记忆性搜索

例子:

LeetCode 140 Word Break II
这是单边catalan

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
def wordBreak(self, s: str, wordDict: List[str]) -> List[str]:
wordSet = set()
for word in wordDict:
wordSet.add(word)
cache = {}
res = self.dfs(s, wordSet, cache)
return [] if len(res) == 1 and not res[0] else res

def dfs(self, s, wordSet, cache):
if not s:
return ['']
if s in cache:
return cache[s]
res = []
for i in range(len(s)):
if s[:i + 1] not in wordSet:
continue
li = self.dfs(s[i + 1:], wordSet, cache)
for ss in li:
res.append((s[:i + 1] + ' ' + ss).strip())

cache[s] = res
return res

例子:

返回结果是解的集合,所以终止条件返回也需要是一个[None]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# catelan dfs (type 4) LeetCode 095 Unique Binary Search Trees II
# return the root of all the possible trees
def generateTrees(self, n: int) -> List[TreeNode]:
nums = [_ + 1 for _ in range(n)]
return self.dfs4(nums, 0, n)

def dfs4(self, nums, start, end): # [start, end)
if start >= end:
return [None] # remember becaues we want the 2 for-loop happen
res = []
for i in range(start, end):
left_root_nodes = self.dfs4(nums, start, i) # 0, 0
right_root_nodes = self.dfs4(nums, i + 1, end) # 1, 1
for left_root_node in left_root_nodes:
for right_root_node in right_root_nodes:
node = TreeNode(nums[i])
node.left = left_root_node
node.right = right_root_node
res.append(node)
return res

应用题型:

LeetCode 095 Unique Binary Search Trees II
LeetCode 241 Different Ways to Add Parentheses LeetCode 761 Special Binary String

Java代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/*
* graph: 邻接表
* visited: 记录已访问节点,避免重复访问
* start: DFS的根节点
*/
public void dfs(HashMap<Integer, LinkedList<Integer>> graph, HashSet<Integer> visited, int start){
if(visited.contains(start)){
return;
}
visited.add(start);
System.out.print(start+",");
for(Integer child : graph.get(start)){
dfs(graph, visited, child);
}
}

算法分析:

时间复杂度为O(n),h为树的高度,空间复杂度O(h),如果用系统栈,可理解其为O(1)。

算法思路:

hasNext, next都涉及计算下一个元素,大部分题目是先计算再返回。只有BST是先返回再计算,因为BST的下一个节点取决于要返回的节点,若返回了,就无法知道下一个节点。

注意事项:

  1. hasNext中,while循环找到下一个符合条件的元素
  2. next中取值后指针要后移

Python代码:

1
2
3
4
5
6
7
8
9
10
11
def __init__(self):
self.stack = []
<add to stack>

def next(self) -> int:
return self.stack.pop() if self.hasNext() else None

def hasNext(self) -> bool:
while <until find the next element>:
<calculate>
return <next element>

例子:

LeetCode 341 Flatten Nested List Iterator
实现Nested List的Iterator。Nested List是NestedInteger的数组,NestedInteger可以是int,也可以是Nested List
nestedList = [NestedInteger]
NestedInteger 用isInteger()来判断
-> 2 by getInteger()
-> [2, 3] by getList()

1 记得在next和hasnext去pop不是stack[-1]

  1. Iterator题目都是用Stack,比如BST Iterator
  2. next或hasNext要迭代到第一个integer为止
  3. hasNext和next要对第三步保持一致: next要call self.hasNext()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class NestedIterator(TestCases):

def __init__(self, nestedList: [NestedInteger]):
self.stack = []
for n in reversed(nestedList):
self.stack.append(n)

def next(self) -> int:
return self.stack.pop() if self.hasNext() else None


def hasNext(self) -> bool:
while self.stack and not self.stack[-1].isInteger():
n = self.stack.pop()
for m in reversed(n.getList()):
self.stack.append(m)
return self.stack

应用题型:

LeetCode 251 Flatten 2D Vector LeetCode 281 Zigzag Iterator LeetCode 341 Flatten Nested List Iterator LeetCode 173 Binary Search Tree Iterator

算法分析:

next操作时间复杂度为O(N + V)/NO(1),N为所有数,V为复合结构数

Free mock interview