I need to find the minimum depth of a binary tree. My code fails on this test case: [-9, -3, 2, null, 4, 4, 0, -6, null, -5].
Given a binary tree, find its minimum depth Example:
Given binary tree [3, 9, 20, null, null, 15, 7],
3
/ \
9 20
/ \
15 7
return its minimum depth = 2.
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public int count(TreeNode root) {
if (root == null) {
return 0;
}
return 1 + Math.max(count(root.left), count(root.right));
}
public int minDepth(TreeNode root) {
int left = 0, right = 0;
if (root == null) {
return 0;
}
if (root.right == null) {
return 1 + count(root.left);
}
if (root.left == null) {
return 1 + count(root.right);
}
left = count(root.left);
right = count(root.right);
return 1 + Math.min(left, right);
}
}
output = 4
expected = 3
I believe the problem is in using Math.max instead of Math.min
public int minDepth(TreeNode root)
{
if(root == null)
return 0;
return 1 + Math.min(minDepth(root.left), minDepth(root.right));
}
The helper function seems like overkill here; it's easier to put all of the logic into one function and pass counts up the stack.
There are 3 cases:
If this node is null, return 0.
If there are no children, this node is a leaf. Return 1.
If there is a left and/or right child, this node is an interior node. Recursively compute the minimum depths for any present children and add 1 to count the current node. If either left or right child is missing, we'll ignore it in the computation by coalescing its minimum value to infinity.
Here's the code:
public int minDepth(TreeNode root) {
if (root == null) {
return 0;
}
else if (root.left == null && root.right == null) {
return 1;
}
int left = root.left == null ? Integer.MAX_VALUE : minDepth(root.left);
int right = root.right == null ? Integer.MAX_VALUE : minDepth(root.right);
return Math.min(left, right) + 1;
}
Related
I'm trying to find the minimum height of a tree. I modified my original algorithm for finding the max height of a tree (but this time, just using Math.min instead of Math.max).
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public int minDepth(TreeNode root) {
if(root == null){return Integer.MAX_VALUE;}
if(root.left == null && root.right == null){return 1;}
int left = minDepth(root.left);
int right = minDepth(root.right);
return Math.min(left, right) + 1;
}
}
It was able to pass a normal tree, and the Integer.MAX_VALUE is there for the test case of
2
\
3
\
4
\
5
However, the code will NOT pass the test case of simply having an empty input "[]".
Is there any changes I can make to this code that will pass? I'm scratching my head and wondering if I should delete it and start from scratch. I feel very close, though.
LC Question: https://leetcode.com/problems/minimum-depth-of-binary-tree/
The problem in your code, is when the tree is skewed for example, it will return the minimum depth-value for subtree's it traversed so far.
if you consider the following tree:
2
\
3
\
4
\
5
it should return -2147483648.
carefully check the left and right subtree of root, which is 2,
left subtree depth value: Integer.MAX_VALUE (+1) = -2147483648
right subtree depth value: 4 (+1) = 5
now check next element which is 3,
minimum value found so far: -2147483648
right subtree depth value: 3 (+1) = 4
now check next element which is 4,
minimum value found so far: -2147483648
right subtree depth value: 2 (+1) = 3
and so on.. and at the end will come up with the minimum number we have found so far, which is -2147483648 or in case of 2147483647 when the tree is empty or null.
you need to change the logic in which case it should take minimum depth-value for maximum depth-ed node:
I wrote one solution for you, check if it works:
int min = Integer.MAX_VALUE;
public int minDepth(TreeNode root) {
if(root == null){
return 0; /* return 0 when the tree is empty */
}
/* visit each node in DFS manner, and found maximum depth-ed node possible */
minDepth(root, 0);
return min+1;
}
private void minDepth(TreeNode root, int count){
if(root == null){
return;
}else if(root.left == null && root.right == null){
/* replace the minimum value with maximum-depth node counter */
if(min > count){
min = count;
}
}else{
count += 1;
minDepth(root.left, count);
minDepth(root.right, count);
}
I have to find a value and the distance between the distant nodes from a bst. I've already made an method which can find the distance between both, but how I can pick a value inside the node?
public int diameter(Node root)
{
// base case if tree is empty
if (root == null)
return 0;
// get the height of left and right sub-trees
int lheight = height(root.left);
int rheight = height(root.right);
// get the diameter of left and right sub-trees
int ldiameter = diameter(root.left);
int rdiameter = diameter(root.right);
/* Return max of following three
1) Diameter of left subtree
2) Diameter of right subtree
3) Height of left subtree + height of right subtree + 1
*/
return Math.max(lheight + rheight + 1,
Math.max(ldiameter, rdiameter));
}
You should provide a reference to the furthest node; the way it is written, the function only return the distance. Please be aware that I did not compile the snippet so it may need adjustements, but just to give the idea:
class HeightResult {
int value;
Node node;
}
class DiameterResult {
int value;
Node left;
Node right;
DiameterResult(int value, Node left, Node right) {
this.value = value;
this.left = left;
this.right = right;
}
}
public DiameterResult diameter(Node root) {
// base case if tree is empty
if (root == null)
return 0;
// get the height of left and right sub-trees
HeightResult lheight = height(root.left);
HeightResult rheight = height(root.right);
// get the diameter of left and right sub-trees
DiameterResult ldiameter = diameter(root.left);
DiameterResult rdiameter = diameter(root.right);
/* Return max of following three
1) Diameter of left subtree
2) Diameter of right subtree
3) Height of left subtree + height of right subtree + 1
*/
if (lheight.value + rheight.value + 1 >= Math.max(ldiameter.value, rdiameter.value)) {
return new DiameterResult(lheight.value + rheight.value + 1, lheight.node, rheight.node);
} else if (ldiameter.value >= rdiameter.value) {
return ldiameter
} else {
return rdiameter;
}
}
}
Let me be very clear that am not getting what Horizontal distance is.
But still from my point of view. Horizontal distance means : missing or existing nodes between given nodes at the same level.
In my case when I try to find out the distance between 7 & 1 am getting output i.e 2. That's why am thinking the way mentioned above.
But if I try to find out the distance between 9 & 6 am getting output as 4.
For Example, in the given tree, the distance between node 7 and 1 which are at same level is 2
(considering right child of node 2 and left child of node 3)
This image will help you to understand
And Following is the code am using to check the distance.
public class BinaryHorizontalDistance
{
public int findDistance(Node root, int n1, int n2)
{
int leftNodeToRootNode = Pathlength(root, n1, "leftNodeToRootNode") - 2;
int rightNodeToRootNode = Pathlength(root, n2,"rightNodeToRootNode") - 2;
int lcaData = findLCA(root, n1, n2).data; //LCA->Lowest Common Ancestor
int lcaDistance = Pathlength(root, lcaData,"lcaDistance") - 1;
return (leftNodeToRootNode + rightNodeToRootNode) - 2 * lcaDistance;
}
public int Pathlength(Node root, int n1,String callingFrom)
{
if (root != null)
{
int x = 0;
if("rightNodeToRootNode" == callingFrom)
{
if(root.left ==null && root.right ==null)
{
//do nothing
}
else if(root.left ==null || root.right ==null)
{
System.out.println("counting the position where the node is not present is : " + root.data);
}
if ((root.data == n1) || (x = Pathlength(root.left,
n1,"rightNodeToRootNode")) > 0 || (x = Pathlength(root.right,
n1,"rightNodeToRootNode")) > 0)
{
return x + 1;
}
}
if("rightNodeToRootNode" != callingFrom )
{
if ((root.data == n1) || (x = Pathlength(root.left,
n1,"leftNodeToRootNode")) > 0 || (x = Pathlength(root.right,
n1,"leftNodeToRootNode")) > 0)
{
return x + 1;
}
}
return 0;
}
return 0;
}
public Node findLCA(Node root, int n1, int n2)
{
if (root != null)
{
if (root.data == n1 || root.data == n2)
{
return root;
}
Node left = findLCA(root.left, n1, n2);
Node right = findLCA(root.right, n1, n2);
if (left != null && right != null)
{
return root;
}
if (left != null)
{
return left;
}
if (right != null)
{
return right;
}
}
return null;
}
public static void main(String[] args) throws java.lang.Exception
{
Node root = new Node(5);
root.right = new Node(2);
root.left = new Node(3);
root.right.right = new Node(7);
//root.right.left = new Node(78);
root.right.right.right = new Node(9);
root.left.left = new Node(1);
//root.left.right = new Node(22);
root.left.left.right = new Node(4);
root.left.left.left = new Node(6);
BinaryHorizontalDistance binaryTreeTest = new BinaryHorizontalDistance();
System.out.println("Distance between 7 and 1 is : " +
binaryTreeTest.findDistance(root,9, 6));
}
}
class Node
{
int data;
Node left;
Node right;
public Node(int data)
{
this.data = data;
this.left = null;
this.right = null;
}
}
An explanation with an example would be appreciated. And happy to explain further
you know the definition:
if you are a left child: count -1,
if you are a right child: count +1
5
/ \
4 6
here, to compute h(4,6)
4 is left child of 5: -1
6 is right child of 5: +1
h(4,6) = 0
5
/ \
4 6
\
2
here, to compute h(2,6), 2 is right child of 4 (** apparently if node is an only child it has to be considered as a right child):
so h(2,4)=+1 recall
h(4,6)=0
so h(2,6) = 1
regarding one of your examples, say h(9,6)
h(9,7) = 2
h(2,3) = 0
h(3,1) = 1 (1 only child so +1)
h(1,6) = 1 (same)
total: 4
** I suppose +1 has been chosen for consistency but I just have observed it
Code in Python
"""
Given a binary tree, find the horizontal distance between 2 nodes at the same level, also counting the position where the node is not present.
"""
# binary tree node
class Node:
# Constructor to create new node
def __init__(self, data):
self.data = data
self.left = self.right = None
self.val = data
# This function returns pointer to LCA of two given values n1 and n2.
def LCA(root, n1, n2):
# Base case
if root is None:
return None
# If either n1 or n2 matches with root's
# key, report the presence by returning
# root
if root.data == n1 or root.data == n2:
return root
if root.data == None or root.data == None:
return None
# Look for keys in left and right subtrees
left = LCA(root.left, n1, n2)
right = LCA(root.right, n1, n2)
if left is not None and right is not None:
return root
# Otherwise check if left subtree or
# right subtree is LCA
if left:
return left
else:
return right
# function to find distance of any node
# from root
def findLevel(root, data, d, level):
# Base case when tree is empty
if root is None:
return
# Node is found then append level
# value to list and return
if root.data == data:
d.append(level)
return
findLevel(root.left, data, d, level + 1)
findLevel(root.right, data, d, level + 1)
# function to find distance between two
# nodes in a binary tree
def findDistance(root, n1, n2):
lca = LCA(root, n1, n2)
# to store distance of n1 from lca
d1 = []
# to store distance of n2 from lca
d2 = []
# if lca exist
if lca:
# distance of n1 from lca
findLevel(lca, n1, d1, 0)
# print(d1)
# distance of n2 from lca
findLevel(lca, n2, d2, 0)
# print(d2)
return d1[0]
else:
return -1
def inorder(root):
if root:
# Traverse left
inorder(root.left)
# Traverse root
ls.append(root.val)
# print(str(root.val) + "->", end='')
# Traverse right
inorder(root.right)
def height(root):
if root:
return 1+max(height(root.left), height(root.right))
else:
return -1
# Driver program to test above function
root = Node(5)
root1 = root.val
root.left = Node(3)
root.right = Node(2)
root.left.left = Node(1)
root.left.left.left = Node(6)
root.left.left.right = Node(4)
root.right.right= Node(7)
root.right.right.right= Node(9)
# print("Height of the Binary Tree: ", height(root))
treeHeight = height(root)
# Total nodes required to compelete binary tree
totalNodes = 2**(treeHeight + 1) -1
# print("Required Nodes : ",2**(treeHeight + 1) -1)
ls =[]
# print("Inorder traversal ")
inorder(root)
index = ls.index(root1)
treeLeft =[]
treeRight = []
for i in range(len(ls)):
if i < index:
treeLeft.append(ls[i])
elif i == index:
pass
else:
treeRight.append(ls[i])
print("Nodes at Same Level and horizontal distance between 2 nodes ")
print()
print("---**---**---**---**---**---**---**---**---**---**---**---**---**---")
print()
for i in treeLeft:
for j in treeRight:
# print("Dist(",i,root1,") = ", findDistance(root, i, root1))
# print("Dist(",root1,j,") = ", findDistance(root, j, root1))
if findDistance(root, i, root1) == findDistance(root, j, root1):
print("Nodes are : (",i,",",j, ") & Horizontal Distance between (",i,",",j,"): ", findDistance(root, i, root1))
print()
print("---**---**---**---**---**---**---**---**---**---**---**---**---**---")
print()
print("count of the position where the node is not present : ", totalNodes - len(ls))
print()
print("---**---**---**---**---**---**---**---**---**---**---**---**---**---")
"""
Program Output :
Nodes at Same Level and horizontal distance between 2 nodes
---**---**---**---**---**---**---**---**---**---**---**---**---**---
Nodes are : ( 6 , 9 ) & Horizontal Distance between ( 6 , 9 ): 3
Nodes are : ( 1 , 7 ) & Horizontal Distance between ( 1 , 7 ): 2
Nodes are : ( 4 , 9 ) & Horizontal Distance between ( 4 , 9 ): 3
Nodes are : ( 3 , 2 ) & Horizontal Distance between ( 3 , 2 ): 1
---**---**---**---**---**---**---**---**---**---**---**---**---**---
count of the position where the node is not present : 7
---**---**---**---**---**---**---**---**---**---**---**---**---**---
"""
For example, I have a tree:
8
_ _
/ \
1 48
/ / \
0 40 50
/
10
When I add 10 to the TREE, my method decides, that this AVL tree is not an AVL tree and tries to balance it. I don't understand why the isAVLTree method does not work.
public static boolean isAVLTree(Root root) {
return (findMaxDepth(root) - findMinDepth(root)) <= 1;
}
public static int findMaxDepth(Root root) {
if (root == null ) {
return 0;
}
return 1 + Math.max(findMaxDepth(root.leftSide), findMaxDepth(root.rightSide));
}
public static int findMinDepth(Root root) {
if (root == null) {
return 0;
}
return 1 + Math.min(findMinDepth(root.leftSide), findMinDepth(root.rightSide));
}
Сurrently the method isAVLTree returns false, because
(findMaxDepth(root) - findMinDepth(root)) <= 1
(( 4 - 2) <= 1 ) ->>>>>>>>>>>>>> FALSE
In an AVL tree, the heights of the two child subtrees of any node differ by at most one
(AVL Tree)
That's not what you implemented in your isAVLTree method. The difference between the max depth and min depth doesn't have to be <= 1.
Instead, you should require that both the left and right sub-trees are AVL trees, and in addition the difference between the heights of the left and right sub-trees <= 1.
public static boolean isAVLTree(Root root)
{
if (root == null) {
return true;
}
return Math.abs(findMaxDepth(root.leftSide) - findMaxDepth(root.rightSide)) <= 1 &&
isAVLTree (root.rightSide) &&
isAVLTree (root.leftSide);
}
How to find sum of node's height in a binary tree recursively?
Example:
public int totalHeight() {
return totalHeight(root);
}
private int totalHeight(BinaryNode<AnyType> n) {
int totalHeight = 0;
if (n.left == null && n.right == null)
return totalHeight;
if (n.left != null && n.right != null)
return totalHeight + 1
+ Math.max(totalHeight(n.left), totalHeight(n.right));
if (n.left != null)
return totalHeight + 1 + Math.max(totalHeight(n.left), -1);
if (n.right != null)
return totalHeight + 1 + Math.max(-1, totalHeight(n.right));
return totalHeight;
}
I have tried this, but it only get the height of the tree instead of sum of all node's height.
I feel difficult to track the counter in recursion, it seems that the totalHeight set to 0 every recursive call. This is not good.
A simple version would be to do a two-pass process where you first record for each node the height it is at, and then iterate through the nodes to sum them up. This method can be made recursive, but it is easy to do it in just one pass by summing as you calculate the height.
public static int totalHeightSum = 0;
private int calculateHeightAndAdd ( Node n )
{
if ( n == null )
return 0;
int leftHeight = calculateHeightAndAdd ( n.left );
int rightHeight= calculateHeightAndAdd ( n.right);
int myHeight = 1 + Math.max ( leftHeight, rightHeight );
totalHeightSum += myHeight;
return myHeight;
}
Recurcively find height of each node and keep adding to a static variable. Alternately, you could memorize the height and store in each node and then do another recursion to add them up.
The recursion should return the height of the node n and not the total heights of each of the nodes in the subtree.
Given your implementation of the height of a node, let's simply call it height(BinaryNode<?>), you can:
if you have access to all the nodes in a collection:
int sumHeight(List<BinaryNode<?>> nodes) {
int sum = 0;
for (BinaryNode<?> node: nodes) {
sum += height(node);
}
return sum;
}
if you only have access to the nodes in a tree structure:
int sumHeight(BinaryNode<?> node) {
if (node == null) return 0;
return height(node) + sumHeight(node.left) + sumHeight(node.right);
}
It would be interesting to see if there're algo's that can do the calculation in one recursion (maybe some backtracking algo?).
Ok. I have come out a solution.
a) if n == null return 0
b) if n.left == null && n.right == null return 0
c) the total height is total height of left + total height of right + the height of it self
the height of itself is:
1) if left side is larger, then total height of left minus total height of left's left
2) if right side is larger, then total height of right minus total height of right's right
public int totalHeight() {
return totalHeight(root);
}
private int totalHeight(BinaryNode<AnyType> n) {
if (n == null)
return 0;
else if (n.left == null && n.right == null)
return 0;
else
return totalHeight(n.left)
+ totalHeight(n.right)
+ (totalHeight(n.left) > totalHeight(n.right) ? totalHeight(n.left)
- (n.left == null ? 0 : totalHeight(n.left.left))
: totalHeight(n.right)
- (n.right == null ? 0
: totalHeight(n.right.right))) + 1;
}
I am assuming you are not updating heights during insertion.
Solution:
I would traverse through the tree in a inorder way. So I first declare root.height=0.
And then say
BinaryNode right;
BinaryNode left;
BinaryNode parent;
static int level;
int height;
if(left!=null)
{
left.height=left.parent.height+1;
level=level+left.height;
left.yourMethod();
}
if(right!=null)
{
right.height= right.parent.height+1;
level=level+right.height;
right.yourMethod();
}
So you will now have level that stores all the heights.
Alternative method can be Breadth first search traversal using a queue, but the answer would be the same.
Hope this helps.
void addHeights(class tree* root, int depth, int& sum)
{
if(root)
{
addHeights(root->left, depth+1, sum);
addHeights(root->right, depth+1, sum);
sum += depth;
}
}
public int sum(){
return sum(root);
}
private int sum(BinaryNode <?> n){
if(n == null)
return 0;
else
return n.data + sum(n.left) + sum(n.right);
}
I need more data to assess your code though I am assuming that you called the data inside the node "data".
So if the node is null it means you have reached the end of the tree and returns 0. Otherwise it takes the data and traverses towards the left then to the right. With each recursion they are being added until they are no more nodes left to be added.
private int maxHeight(BinaryNode<AnyType> n) {
if (n ! = null) return 0;
int leftheight = maxHeight(n.left);
int rightheight = maxHeight(n.right);
return (leftheight > rightheight) ? leftheight + 1 : rightheight + 1;
}
So far you have known the 4 cases to count the height
The essence is to continue to go left or right node if the left child or the right child exist.
if exist, return 1.
The counting function goes in the last statement. That is to get the largest height counted.
The main course is to get familiar with recursion and the programming stack when the method is working.