(FB) 从 Binary Tree Path 看如何递归转迭代
例题:给定 Binary Tree,print 所有 root - leaf 的 path.
Input : Root A
Output :
A,B,C
A,D,E
A,D,F
递归:
比较简单直接,就是在树上 DFS + backtrack,带着当前节点 root 和当前路径 list 递归处理即可。这题的结构和 LC 那道 Binary Paths 一样。
迭代解法 1:
Queue,空间占用和时间都高一些。
基本思路就是用一个 Queue 存所有当前的 path,队列中的 path 数量与进出关系都和正常的 level order traversal 完全一样,每次队列末尾的节点,都是 current node.
中间 poll 的时候看到叶子节点,就把 list 输出出来就好。
这种解法的问题一是空间占用是 O(N) 的,相比 Stack 高;二是每次生成新 node 的时候其实是在做一次 collection 的 copy 操作,时间复杂度上也不经济。
迭代解法 2:
Stack + HashSet
迭代解法 3: Stack + 自定义 StackFrame
这种做法最有意思,我也最喜欢,觉得只要有合适的 field 属性,很容易 generalize 到各种其他递归解法中。
首先对于二叉树,我们可以这样定义 StackFrame 的三个状态:
0 : 刚入栈,未访问子树;
1 : 正在访问左子树,返回代表左子树访问完毕;
2 : 正在访问右子树,返回代表右子树访问完毕;
这样代码如下,每次 stack 里存的,都是当前路径 (配合一个 List 做高效 print path 操作),而每次栈顶的 StackFrame 都记录了当前 node 的访问状态和下一步的动向。
这种 0/1/2 的状态表示方式看着有点像 Graph 里面做 DFS / BFS 的标注,其实不完全一样,只是在这题我们的树一定是二叉而已。
对于多叉树的情况,改动也不会很难;这次 index 代表着 “下一个要访问的 child index”,当 index == children.size() 的时候,我们就可以知道当前 node 的所有子节点都访问完了。
Last updated