问题
Recursive mechanism to find max depth of depth of binary tree is very straightforward, but how can we do it efficiently without recursion as I have large tree where I would rather avoid this recursion.
//Recursive mechanism which I want to replace with non-recursive
private static int maxDepth(Node node) {
if (node == null) return 0;
return 1 + Math.max(maxDepth(node.left), maxDepth(node.right));
}
PS: I am looking for answers in Java.
回答1:
This variant uses two stacks, one for additional nodes to explore (wq
) and one always containing the current path from the root (path
). When we see the same node on the top of both stacks it means we've explored everything below it and can pop it. This is the time to update the tree depth too. On random or balanced trees the additional space should be O(log n), in the worst case O(n), of course.
static int maxDepth (Node r) {
int depth = 0;
Stack<Node> wq = new Stack<>();
Stack<Node> path = new Stack<>();
wq.push (r);
while (!wq.empty()) {
r = wq.peek();
if (!path.empty() && r == path.peek()) {
if (path.size() > depth)
depth = path.size();
path.pop();
wq.pop();
} else {
path.push(r);
if (r.right != null)
wq.push(r.right);
if (r.left != null)
wq.push(r.left);
}
}
return depth;
}
(Shameless plug: I had this idea for using dual stacks for non-recursive traversals a few weeks ago, check for a C++ code here http://momchil-velikov.blogspot.com/2013/10/non-recursive-tree-traversal.html not that I claim I was the first to invent it :)
回答2:
The recursive approach you've described is essentially a DFS over the binary tree. You can implement this iteratively if you'd like by storing an explicit stack of nodes and keeping track of the maximum depth encountered.
Hope this helps!
回答3:
I have written following logic to do find max and min depth which doesn't involve recursion and without increasing the space complexity.
// Find the maximum depth in the tree without using recursion
private static int maxDepthNoRecursion(TreeNode root) {
return Math.max(maxDepthNoRecursion(root, true), maxDepthNoRecursion(root, false));
}
// Find the minimum depth in the tree without using recursion
private static int minDepthNoRecursion(TreeNode root) {
return Math.min(maxDepthNoRecursion(root, true), maxDepthNoRecursion(root, false));
}
private static int maxDepthNoRecursion(TreeNode root, boolean left) {
Stack<TreeNode> stack = new Stack<>();
stack.add(root);
int depth = 0;
while (!stack.isEmpty()) {
TreeNode node = stack.pop();
if (left && node.left != null) stack.add(node.left);
// Add the right node only if the left node is empty to find max depth
if (left && node.left == null && node.right != null) stack.add(node.right);
if (!left && node.right != null) stack.add(node.right);
// Add the left node only if the right node is empty to find max depth
if (!left && node.right == null && node.left != null) stack.add(node.left);
depth++;
}
return depth;
}
回答4:
If you can maintain left and right values at each node, it can be done.
http://leetcode.com/2010/04/maximum-height-of-binary-tree.html.
Possible duplicate: Retrieving a Binary-Tree node's depth non-recursively
回答5:
Another way is to use Level order traversal
, where tree height is equal to the number of level of a tree. (It can only be use to calulate the minimal height of a tree.)
public int maxDepth(TreeNode root) {
if (root == null) return 0;
LinkedList<TreeNode> arr = new LinkedList<TreeNode>(); // queue for current level
LinkedList<TreeNode> tmp = new LinkedList<TreeNode>(); // queue for next level
arr.add(root);
int res = 0; // result
TreeNode node; // tmp node
while (true) {
while (!arr.isEmpty()) {
node = arr.poll();
if (node.left != null) tmp.add(node.left);
if (node.right != null) tmp.add(node.right);
}
res++;
if (tmp.isEmpty()) break;
arr = tmp;
tmp = new LinkedList<TreeNode>();
}
return res;
}
回答6:
Using a Array to store a layer of nodes, each time find a new layer. the depth plus one.
public int maxDepth2(TreeNode root){
if(root == null){
return 0;
}
int depth = 0;
ArrayList<TreeNode> oneLayer = new ArrayList<TreeNode>();
oneLayer.add(root);
while(!oneLayer.isEmpty()){
ArrayList<TreeNode> newLayer = new ArrayList<TreeNode>();
for(TreeNode node:oneLayer){
if(node.right!=null){
newLayer.add(node.right);
}
if(node.left!=null){
newLayer.add(node.left);
}
}
oneLayer = newLayer;
depth++;
}
return depth;
}
回答7:
Here is a BFS solution:
private class NodeHeight
{
public Node node;
public int height;
public NodeHeight(Node n, int height)
{
node = n;
this.height = height;
}
}
public int GetHeightBfs(Node root)
{
if(root == null)
return 0;
else
return GetHeightBfs(new NodeHeight(root, 1))
}
private int GetHeightBfs(NodeHeight root)
{
int maxHeight = int.Min;
int minHeight = int.Max;
var q = new Queue<Node>();
q.Enqueue(root);
while(q.length > 0)
{
var nodeHeight = q.Dequeue();
var node = nodeHeight.node;
int height = nodeHeight.height;
if(node.left == null && node.right == null)
{
maxHeight = Math.max(maxHeight, height);
minHeight = Math.min(minHeight, height);
}
if(node.left != null)
q.Enqueue(new NodeHeight(node.left, height + 1);
if(node.right != null)
q.Enqueue(new NodeHeight(node.right, height + 1);
}
return maxHeight;
}
Note that you can also return minHeight. To make it DFS just replace Queue with Stack.
来源:https://stackoverflow.com/questions/19886297/finding-max-depth-of-binary-tree-without-recursion