In Java, STACK is usually a size limited memory area.By default, a several thousands levels recursion call would easily eat up all the space and throw StackOverFlowException - this is something you have to keep in mind
Iterative way is good because it needs much less space of STACK(There is probably only O(1) method call levels, so O(1) space on STACK.)
It is not easy to convert all recursion solutions to a “while loop” solution without any other auxiliary data structures’ help.
There are two paths of recursion need to follow instead of one, and we need to finish the first branch, then the second one.
In this case, we will need something else to help us:
The recursion is internally done by using STACK to maintain the method call levels and directions, we can simulate this ourselves, so a stack will be needed.
The difference is, we use our own stack and the space used by our own stack is on HEAP. The space consumed on STACK is trivial.
We do not change the total space consumption, but we move out the space consumption of STACK to HEAP!!!
classSolution(object): definorderTraversal(self, root): ifnot root: return [] left = self.inorderTraversal(root.left) right = self.inorderTraversal(root.right) return left + [root.val] + right
Iteration (Stack + cur)
The problem is, we can not throw away the root in the stack before we traversed all the nodes in left subtreee. How can we know we have already traversed all the nodes in left sub?
The root is the top element in the stack, use a helper node to store the next “visiting” node and subtree.
1 When helper node is not null, we should traverse the subtree, so we push helper and we go left
2 When helper is null, means the left subtree of the roots finished, the root is the top element in the stack. We can print the top, and let helper = top.right.(traverse the left subtree firtst, then top. then right subtree)
3 do 1 and 2 until helper is null and there is no nodes left in the stack
# 写法1. classSolution(object): definorderTraversal(self, root): ifnot root: return [] res, stack = [], [] cur = root while stack or cur: while cur: stack.append(cur) cur = cur.left cur = stack.pop() res.append(cur.val) cur = cur.right return res
stack, res = [], [] cur = root while stack or cur: if cur: stack.append(cur) cur = cur.left else: cur = stack.pop() res.append(cur.val) cur = cur.right return res
classSolution(object): definorderTraversal(self, root): ifnot root: return [] left = self.inorderTraversal(root.left) right = self.inorderTraversal(root.right) return left + right + [root.val]
Iteration
解法1. Two Stacks
left->right->root (reverse)=> root->right->left
Preorder -> Postorder
1 2 3 4 5 6 7 8 9 10 11
classSolution(object): defpostorderTraversal(self, root): # Pre-order, but root->right->left stack, res = [root], [] while stack: node = stack.pop() if node: res.append(node.val) stack.append(node.left) stack.append(node.right) return res[::-1]
What is the drawback of two stacks solution, if we deal with the nodes on the fly? (Online) Need to store everything in memory before we can get the whole post order traversal sequenct.
解法2. Stack + cur + prev
The problem is, we need to traverse both left and right subtrees first, then we can eliminate the root from the stack. We need an mechanism to know, when we finished visiting all subtrees’ nodes.
What we need to know?
Direction!!!!!!!
we are visiting down? or returning from left? or returning from right?
思路1. 细分三种case The root is the top element in the stack Maintain a previous Node, to record the previous visiting node on the tracersing path, so that we know what the direction we are taking now and what is the direction we are taking next.
root = stack.top
if previous is null -> going down(left subtree has priority)
if previous is current’parent -> going down (left subtree has priority)
if previous == current.left -> left subtree finished, going current.right
if previous == current.right -> right subtree finished, pop current, going up.
# Inorder Demo Morris Traversal classSolution(object): definorderTraversal(self, root): ifnot root: return [] res = [] cur = root while cur: ifnot cur.left: res.append(cur.val) cur = cur.right else: # 1 Find Inorder Predecessor of cur prev = cur.left while prev.right and prev.right != cur: prev = prev.right
# 2 Connect or Restore the Pointer ifnot prev.right: prev.right = cur cur = cur.left else: prev.right = None res.append(cur.val) cur = cur.right return res