题目大意:
给定一个二叉树,返回它的 前序 遍历。
示例:
输入: [1,null,2,3]
1
\
2
/
3
输出: [1,2,3]
进阶: 递归算法很简单,你可以通过迭代算法完成吗?
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/binary-tree-preorder-traversal
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
详解:
首先分析,无论前序中序肯定都是深度优先,采用栈
- 首先new一个列表(存储结果),new一个栈, 定义一个当前待处理的节点(初始值为root节点)
- 判断当前节点是否为空,为空退出循环,不为空先将当前节点直接输入到结果,然后执行第3步。(因为是前序遍历,所以当前节点直接输入到结果)
- 判断左子节点,不为空,压栈,更新当前节点,执行第2步(因为是前序遍历,所以左右子节点优先左节点。)
- 判断右子节点,不为空,压栈,更新当前节点,执行第2步
- 这一步分析比较长,写成一段:
-
如果执行到了这里这里,说明当前节点的左右子节点都是空的,且当前节点已经输出到结果(第2步输入的),但是还没有压栈(其实已经没有压栈的必要了,因为结果也输出了,又没有子节点)。这个时候就要考虑他的父节点了,父节点在哪呢?栈里!可以看到上面先执行第3步,那么每一个父节点如果他有左节点,那么他的右节点就没有遍历处理(因为随着循环去处理他的左节点了)。所以现在要依次考虑每一个父节点右子节点(此时不需要考虑父节点的左子节点,不理解的自己去面壁思考)
-
既然依次考虑,所以需要一个循环,如果当前栈顶节点的右子节点不为空,且右子节点不等于当前节点(这个且非常重要,不然就可能会重复处理右子节点),说明当前右子节点还没有处理,更新当前节点,退出循环,执行第2步。否则直接出栈当前节点,接着判断下一个栈顶,直到栈空了
- 至此结束
再详细的思路也不及代码片行,那直接贴代码
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> list = new ArrayList<>();
if(root == null){
return list;
}
Stack<TreeNode> stack = new Stack<>();
TreeNode tmp = root;
while (tmp != null){
list.add(tmp.val);
if(tmp.left != null){
stack.push(tmp);
tmp = tmp.left;
continue;
}
if(tmp.right != null){
stack.push(tmp);
tmp = tmp.right;
continue;
}
while (true){
if(stack.isEmpty()){
tmp = null;
break;
}
TreeNode peek = stack.peek();
if(peek.right != null && peek.right != tmp){
tmp = peek.right;
break;
}
tmp = stack.pop();
}
}
return list;
}
最后贴一下效率: