Hi I came across a code to find the maximum height of a binary tree.
In this code why is there a +1 in the return statement?
public int maxDepth(TreeNode root) {
if (root == null) {
return 0;
}
return Math.max(maxDepth(root.left), maxDepth(root.right)) + 1;
}
If there wasn't, the result would always be 0.
The max height of a binary tree is the max height of the child having a larger max height (that's the Math.max(maxDepth(root.left), maxDepth(root.right)) part) + 1 for the root of the tree.
Consider a tree consisting of a single root node. Then the following return statement would return 1, which is what we expect:
return Math.max(maxDepth(root.left), maxDepth(root.right)) + 1;
return Math.max(0, 0) + 1;
return 1;
As your base case shows, an empty tree would have a height of zero, and you can build up to taller trees' height using induction.
Related
Trying to solve this LC Easy: https://leetcode.com/problems/minimum-depth-of-binary-tree/
Which is to find the minimum depth (number of nodes on shortest path) of a tree.
I was able to create a "findheight" function which gives me the height of a tree.
My logic was to use findheight to find the height of both subtrees (left and right) of a root node, and then return the minimum between the two heights.
class Solution {
public int minDepth(TreeNode root) {
if(root == null){return 0;}
int left = findHeight(root.left);
int right = findHeight(root.right);
//unbalanced tree, only one subtree
if(left == 0 || right == 0){
return Math.max(left,right) + 1;
}
return Math.min(left,right) + 1 ;
}
public int findHeight(TreeNode root){
if(root == null){return 0;}
int left = findHeight(root.left);
int right = findHeight(root.right);
return Math.max(left,right) + 1;
}
}
It won't pass the test case:
[-9,-3,2,null,4,4,0,-6,null,-5]
Or:
Output:
4
Expected:
3
My thought process right now is that when I use "findHeight", I'm returning back the 'max' height per left and right subtree. In this test case, I should be returning back the minimum height.
I changed my code to "Math.min" in another iteration, but that doesn't work either.
Any ideas or theories why? So confused!! Should I just abandon this approach altogether?
Issue in current code
//unbalanced tree, only one subtree
if(left == 0 || right == 0){
return Math.max(left,right) + 1;
}
The above lines of code checks the imbalance only at root level. It does not recursively check imbalance at lower levels.
Check imbalance at every level
public int minDepth(final TreeNode node) {
if (node == null) {
return 0;
}
final int left = minDepth(node.left);
final int right = minDepth(node.right);
// if both paths exist, then return the minimum
if (node.left != null && node.right != null) {
return Math.min(left, right) + 1;
} else {
// if zero or one path exists return that path (so take maximum)
return Math.max(left, right) + 1;
}
}
I have the trivial solution to counting the number of nodes in a complete binary tree:
public int countNodes(TreeNode root) {
if (root == null) { return 0; }
return 1 + countNodes(root.left) + countNodes(root.right);
}
I understand this. However, I am aware that it is inefficient as it has to visit each node. I have another solution that I found online:
public int countNodes(TreeNode root) {
if(root==null)
return 0;
int left = getLeftHeight(root)+1;
int right = getRightHeight(root)+1;
if(left==right){
return (2<<(left-1))-1; //having a hard time here
}else{
return countNodes(root.left)+countNodes(root.right)+1;
}
}
public int getLeftHeight(TreeNode n){
if(n==null) return 0;
int height=0;
while(n.left!=null){
height++;
n = n.left;
}
return height;
}
public int getRightHeight(TreeNode n){
if(n==null) return 0;
int height=0;
while(n.right!=null){
height++;
n = n.right;
}
return height;
}
I understand this but I'm not completely sure I understand the condition if (leftHeight == rightHeight). How does this work? Also, could someone please explain the bitwise operation and the reason for why this works? Im not familiar with bitwise operators. Perhaps, if someone could replace that condition with none-bitwise code, and translate whats going on that would be perfect!
The condition (leftHight == rightHight) in a subtree of a tree that we know is a complete tree means that the current subtree is a perfect (full) binary tree. In a perfect binary tree every node has exactly two children except the leaf nodes which have no children.
The bitwise statement (2<<(left-1))-1 is the same as Math.pow(2, left) - 1.
In general powers of 2 can be calculated as below:
2<<0 //equals 2 to the power of 1. 2 is shifted zero bits to the left
2<<1 //equals 2 to the power of 2, 2 is shifted 1 bit to the left
2<<2 // equals 2 to the power of 3, 2 is shifted 2 bits to the left
2<<k // equals 2 to the power of k+1, 2 is shifted k bits to the left
Now if you look at the link above you'll see that the number of nodes in a perfect binary tree of height h is (2**(k+1))-1. That is 2 to the power of (k+1) minus 1.
In the above code left is height+1 notice the plus one in the code. There fore (2<<(left-1))-1 is really calculating the the number nodes in that perfect binary tree.
I am having trouble with a basic binary search tree that I have created in Java. I am trying to output the tree structure in the console with prepended spaces before a nodes value with respect to how deep the node is.
For some reason my printTree() function is outputting a tree structure that seems slightly backwards. I wouldn't think that (5 0.0) would be indented because it would stay as the root in a basic tree like this.
Below is my function and the output:
Note: c creates the root, s adds a key and value, and xp outputs the tree.
private int k;
private float d;
private Node left, right;
public Node(int k) {
this.k = k;
}
public Node(int k, float d) {
this.k = k;
this.d = d;
}
private int height(Node n) {
if (n == null)
return -1;
return 1 + Math.max(height(n.left), height(n.right));
}
private void printTree(Node n) {
if (n == null)
return;
System.out.println(new String(new char[3 * height(n)]).replace("\0", " ") + "(" + n.k + " " + n.d + ") ");
printTree(n.left);
printTree(n.right);
}
Output:
I'm pretty sure that based on my input that 5 should not be indented at all because it would be root node.
I believe that it should look something like (based on a binary search tree):
(5 0.0)
(4 1.2)
(2 3.5)
(6 7.5)
(87 96.5)
(with the correct amount of prepended spaces of course)
Can anybody explain what I'm doing wrong?
You calculate the number of spaces as 3*height(n). height(n) calculates the maximum path length of the left and the right tree, so the root will always be the furthest to the right.
either calculate the height of a node as the length of the path from the node to the root or precalculate the maximum height and set the number of whitespaces for a node to maxHeight - height(n).
I'm having a hard time completing this algorithm to find the height of a tree with multiple children (not binary).
Anyone know where this is going wrong?
private int getHeight(Node<T> root, int height, int result){
if (root.getChildren().size()==0) {
return height;
}
height++;
//Iterate every child
for (Node<T> childNode : root.getChildren()) {
//Get the height again
height =getHeight(childNode, height, result);
//Update if new high result
if (height>result) {
result = height;
}
height = 0;
}
//Return highest point
return result;
}
You are making it harder by adding the height and result parameters.
In the function, find the height of each of the children. Keep the largest. Return 1 + height of the largest.
Sometrhing like this (untested, uncompiled):
private int getHeight(Node<T> root){
int max = 0;
for (Node<T> childNode : root.getChildren()) {
int height = getHeight(childNode);
if (height > max)
max = height;
}
return max + 1;
}
The way you are calculating the height is very awkward and there are many places for possible errors, such as you adding one to the height then getting the height of the children.
I would suggest doing a simpler recursive function that is similar to the one that you are doing.
First of all, you can get rid of the second and third parameters, then you can change the code to look something more like this:
private int getHeight(Node<T> root){
if (root.getChildren().size()==0) {
return 1;
}
int height;
//Iterate every child
for (Node<T> childNode : root.getChildren()) {
//Get the height again
int childHeight = getHeight(childNode);
//Update if new high result
if (childHeight>height) {
height = childHeight;
}
}
//Return highest point
return height + 1;
}
This just returns 1 if the node has no children. Otherwise, it gets the max height of all children and returns that number plus 1.
Im having trouble with a method that finds the height of the closest leaf. What i have just counts all of the leafs. would i have to separate the recursive calls into two conditional statements to check each one independently? any help or suggestions would be appreciated
this is my method
//find the distance to the closest leaf
public int closeLeaf()
{
int distance;
return distance = closeLeaf(root);
}
private int closeLeaf(StringNode n)
{
int dist = 0;
if(n == null)
{
dist = 0;//empty tree
}
else if(n.getLeft()== null && n.getRight()== null)
{
dist++;
}
else
{
dist =closeLeaf(n.getLeft()) + closeLeaf(n.getRight());
}
return dist;
}
Returning values
Please don't do this:
int distance;
return distance = closeLeaf(root);
Just:
return closeLeaf(root);
On to the real question
Here you're adding up the distance to each leaf:
dist = closeLeaf(n.getLeft()) + closeLeaf(n.getRight());
You probably just want to get the minimum of the two values (to tell you the distance to the closest one).
Instead of
dist =closeLeaf(n.getLeft()) + closeLeaf(n.getRight());
which increments dist for every node encountered, use a static/class member variable that gets incremented each time the closeLeaf function is called.
Limit the recursion to finding a leaf, and the value of dist when you find one will give you the height of the closest leaf.