【LEETCODE OJ】Binary Tree Postorder Traversal
Problem Link:
http://oj.leetcode.com/problems/binary-tree-postorder-traversal/
The post-order-traversal of a binary tree is a classic problem, the recursive way to solve it is really straightforward, the pseudo-code is as follows.
RECURSIVE-POST-ORDER-TRAVERSAL(TreeNode node)
if node is NULL
return
else:
RECURSIVE-POST-ORDER-TRAVERSAL(node.left)
RECURSIVE-POST-ORDER-TRAVERSAL(node.right)
visit(node)
The python code is as follows, which is accepted by oj.leetcode.
# Definition for a binary tree node
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None class Solution:
# @param root, a tree node
# @return a list of integers
def postorderTraversal(self, root):
"""
Best way is to DFS the tree in the iterative way by using stack.
However, we first try the recursive version
"""
self.res = []
self.recursiveTraversal(root)
return self.res def recursiveTraversal(self, node):
if node is None:
return
else:
self.recursiveTraversal(node.left)
self.recursiveTraversal(node.right)
self.res.append(node.val)
However, the best way should be iterative. Among pre-order, in-order, and post-order traversals, I think interative post-order traversal is most hard. We need to concern following issues.
1. A child node cannot be put into stack before its parent. This means, we can ONLY put a node while we are going down the tree, and we can ONLY pop a node while we are going up the tree.
2. We need some way to denote we are traversing down or up currently
In practice, I use two pointers corresponding to the concerns above:
go_down: go_down = NULL means we are going down from children to parent, then we need to check if we visit the node or traverse its non-visited sub-tree.
prev_visited: keep track the node just visited which help us to identify the node should be visited or not.
For each iteration, we may be going down or up. In the case of GoDown (go_down != NULL), we just go go_down.left until we touch the bottom of the tree (go_down == NULL), then we begin GoUP. In the case of GoUp (go_down == NULL), we check the top node in the stack (lets say parent). In this case, we are traversing back from the sub-tree of the node parent, and we can guarantee that at least left sub-tree of parent is already visited. So we have three cases according to parent.child: 1) parent.child == NULL, parent has no right sub-tree; 2) parent.child == prev_visited, we just visited parent's right child, which means the right sub-tree of parent is also visited; 3) parent.child != NULL or prev_visited, the right sub-tree is not traversed yet. For case 1) and 2), we just visit the parent (and pop it from the stack) and keep GoUp, for case 3) we need to swith to GoDown case for the right sub-tree (just set go_down = parent.right). The pseudocode is as follows.
ITERATIVE-POST-ORDER-TRAVERSAL(Node root)
go_down = root
prev_visited = NULL
non_visited_parent = Stack()
while (non_visited_parent is not empty) or (go_down is not NULL)
if go_down
non_visited_parent.put(go_down)
go_down = go_down.left
else
parent = non_visited_parent.top() // Get the last non-visited parent without pop
if (parent.right is NULL) or (prev_visited == parent.right)
VISIT(parent)
non_visited_parent.pop()
else
go_down = parent.right
I wrote the solution in OJ.leetcode in python, however LTE again! WTF... I guess the problem may be the stack implementation in python.
class Solution:
# @param root, a tree node
# @return a list of integers
def postorderTraversal(self, root):
"""
DFS the tree in the iterative way by using stack.
The stack stores the parent node in the GoDown path
p: tell us we are traversing down or up
prev_visited: keep track the node just visited
We start from p=root, for each step, there are two cases:
- GoDown (p != NULL). This means p is still a node (even a leaf)
- GoUp (p == NULL). This means we touch the bottom of the tree.
[GoUp] Note that we only VISIT node in GoUp case (p==NULL).
In this case, we get check the top node in the parent_stack,
and check its right child (we do not need to check left child since
p == NULL means we are traversing back and the left sub-tree is visited):
- If the right child is NULL, then VISIT the node and pop it, and keep
GoUp (keep p=NULL and check the top of parent_stack)
- If the right child is just visited, which means we traverse back
from the right sub-tree, also keep GoUp.
- Otherwise, the right sub-tree is not traversed before, then we need
to set p == right child, start GoDown of the right sub-tree
[GoDown] We repeat going left until we touch the bottom of the tree
"""
res = []
p = root # p != None, means we need to go down
prev_visited = None # No node is visited yet
parent_stack = [] # I use the build-in data structure list as the stack
while parent_stack or p is not None:
if p is not None: # GoDown case
parent_stack.append(p)
p = p.left
else: # GoUp case
last_not_visited_parent = parent_stack[-1]
if last_not_visited_parent.right is None or last_not_visited_parent.right == prev_visited:
# In these two cases, we need visit the parent and keep going up
res.append(last_not_visited_parent.val)
prev_node = last_not_visited_parent
parent_stack.pop()
else:
# In this case, we need change to go down for the right sub-tree
p = last_not_visited_parent.right
return res
Also, I also post C++ version here, which is accepted by OJ.leetcode.
/**
* Definition for binary tree
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
#include <stack> class Solution {
public:
vector<int> postorderTraversal(TreeNode *root) {
vector<int> res;
std::stack<TreeNode*> non_visited;
TreeNode * parent = NULL;
TreeNode * go_down = root;
TreeNode * just_visited = NULL;
while (!non_visited.empty() || go_down != NULL) {
if (go_down != NULL) {
non_visited.push(go_down);
go_down = go_down->left;
}
else {
parent = non_visited.top();
if (parent->right == NULL || parent->right == just_visited) {
res.push_back(parent->val);
just_visited = parent;
non_visited.pop();
}
else {
go_down = parent->right;
}
}
}
return res;
}
};
【LEETCODE OJ】Binary Tree Postorder Traversal的更多相关文章
- 【LEETCODE OJ】Binary Tree Preorder Traversal
Problem Link: http://oj.leetcode.com/problems/binary-tree-preorder-traversal/ Even iterative solutio ...
- 【LeetCode OJ】Binary Tree Level Order Traversal
Problem Link: https://oj.leetcode.com/problems/binary-tree-level-order-traversal/ Traverse the tree ...
- 【LeetCode OJ】Binary Tree Zigzag Level Order Traversal
Problem Link: https://oj.leetcode.com/problems/binary-tree-zigzag-level-order-traversal/ Just BFS fr ...
- 【LeetCode OJ】Binary Tree Level Order Traversal II
Problem Link: https://oj.leetcode.com/problems/binary-tree-level-order-traversal-ii/ Use BFS from th ...
- 【LeetCode OJ】Binary Tree Maximum Path Sum
Problem Link: http://oj.leetcode.com/problems/binary-tree-maximum-path-sum/ For any path P in a bina ...
- LeetCode OJ 145. Binary Tree Postorder Traversal
Given a binary tree, return the postorder traversal of its nodes' values. For example:Given binary t ...
- LeetCode OJ:Binary Tree Postorder Traversal(后序遍历二叉树)
Given a binary tree, return the postorder traversal of its nodes' values. For example:Given binary t ...
- 【Leetcode】【hard】Binary Tree Postorder Traversal
Given a binary tree, return the postorder traversal of its nodes' values. For example:Given binary t ...
- 【leetcode】Binary Tree Postorder Traversal
题目: Given a binary tree, return the postorder traversal of its nodes' values. For example: Given bin ...
随机推荐
- 项目文件包含 ToolsVersion="12.0" 设置,但此工具集未知或缺失。
项目属性(Alt+F7),再点常规,常规中有个平台工作集,把V120改成V110或者v100,然后就能正常运行了.
- python读取指定内存的内容
import ctypes as ct t = ct.string_at(0x211000, 20) # (addr, size) print t 最好不要用解释性语言来开发底层,一般用C.
- ADO.NET事务处理,初始回调函数,多张表的数据在同一个DataGridView中展示
执行ADO.NET事务包含四个步骤,接下来以Transaction对象为例介绍. (1)调用SQLConnection对象的BeginTransaction()方法,创建一个SQLTransactio ...
- <<薪资至少10K的一道题,你能拿下吗>>练习
偶尔要写写算法,是我平时用来保持感觉的常用的方法.今天看到园子里一面试题,看了一下感觉也能实现,不过过程确实艰的,自认为自己对算法的感觉还不错.不过这题确实我也用了差不多一下午的时间,基本上把工作时间 ...
- struts2视频学习笔记 24-27(国际化)
课时24 配置国际化全局资源文件.输出国际化信息 1.准备资源文件,添加到src目录下,资源文件的命名格式如下:baseName_language_country.propertiesbaseName ...
- echart饼状图的学习
一.引入js文件 <!--Step:1 引入一个模块加载器,如esl.js或者require.js--> <script src="~/Scripts/esl.js&quo ...
- Spring学习(二)——Spring中的AOP的初步理解[转]
[前面的话] Spring对我太重要了,做个关于web相关的项目都要使用Spring,每次去看Spring相关的知识,总是感觉一知半解,没有很好的系统去学习一下,现在抽点时间学习一下Spring. ...
- (转)虚拟机的桥接模式和NAT模式区别
不管是虚拟机的桥接还是NAT都是占用实机网络的.只不过两种方式有些差异,在通过IP或者拨号连接限速的网络中,差异就很明显了 举个不太恰当但简单的例子,一个百兆的网卡你可以把它想象成一个100车 ...
- Echarts 地图控件tooltip多行显示
直接上代码 var o = { "tooltip": { trigger: 'item', "formatter": function (params) { v ...
- 神奇的Noip模拟试题一试 2 排队
2 排队 (lineup.pas/.c/.cpp) [问题描述] 小sin所在的班有n名同学,正准备排成一列纵队,但他们不想按身高从矮到高排,那样太单调,太没个性.他们希望恰好有k对同学是高的在前,矮 ...