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.
Related
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;
}
}
}
I need to find the sum of odd keys in a Binary Search Tree
public int OddKeys(Node root) {
if (root == null) {
return 0;
}
int value = 0;
if (root.key.compareTo(value) % 2 == 0) {
return value + OddKeys(root.left) + OddKeys(root.right);
}
return value + OddKeys(root.left) + OddKeys(root.right);
}
I am unable to run this because I am confused on how to set "if (root.key.compareTo(value) % 2 == 0)". What would be the correct way to check if the keys are odd or not.
I don't know what that compareTo(0) is hoping to do. If we assume that your keys are simple integers, something like this might be what you're trying to get to:
public int OddKeys(Node root) {
if (root == null)
return 0;
int value = (root.key % 2 == 0)? 0 : 1;
return value + OddKeys(root.left) + OddKeys(root.right);
}
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;
}
I have a project do and I have everything done except for where I need to find the highest level that has the maximum amount of nodes in it. This is the code that I have, but I can't seem to figure out how to do this:
public int fullLevel() {
int height = 1;
int count = 1;
fullLevel(root, height, count);
return height;
}
private int fullLevel(Node temp, int height, int count) {
int height2 = (int) Math.pow(2, height - 1);
if (temp == null) {
return 0;
}
if (count == height2 && temp.left != null && temp.right != null) {
count = 0;
return fullLevel(temp.right, count, height + 1) + fullLevel(temp.left, count, height + 1);
} else if (count != height2) {
return fullLevel(temp.right, count + 1, height) + fullLevel(temp.left, count + 1, height);
} else {
return height;
}
}
The question asks: "Determine the highest level that is full, or, equivalently, has the maximum number of nodes for that level." - Must use recursion. Thanks!
I'm not great at recursion so sorry in advance!
You're on the right track in terms of comparing the number of actual children in each level with the number of possible children for that level. The ideal approach would be to perform a level-order traversal using a queue and return the tallest full level. However, since you're stuck using recursion, the problem becomes one of maintaining count horizontally across recursive calls. A naive solution is to create a list of counts for each height, then return the last full level in that list.
An optimization is only recursing if both children are present--clearly, if a child is missing, it's impossible to have a full level deeper in the tree and we can wrap up our search.
public static int fullLevel(Node root) {
ArrayList<Integer> levelCounts = new ArrayList<>();
levelCount(root, 0, levelCounts);
for (int i = levelCounts.size() - 1; i >= 0; i--) {
if ((int)Math.pow(2, i) == levelCounts.get(i)) {
return i;
}
}
return -1;
}
private static void levelCount(Node root, int height, ArrayList<Integer> levelCounts) {
if (root != null) {
if (height >= levelCounts.size()) {
levelCounts.add(0);
}
levelCounts.set(height, levelCounts.get(height) + 1);
if (root.left != null && root.right != null) {
levelCount(root.left, height + 1, levelCounts);
levelCount(root.right, height + 1, levelCounts);
}
}
}
Output is 2 (zero-indexed) for the following example tree:
____1____
/ \
_2_ __3__
/ \ / \
4 5 6 _7_ <-- tallest full level
/ \ / / \ / \
8 9 10 11 12 13 14
Try it!
You are given a binary tree in which each node contains an integer value.
Find the number of paths that sum to a given value.
The path does not need to start or end at the root or a leaf, but it must go downwards (traveling only from parent nodes to child nodes).
I wrote this up:
EDIT: Fixed algo, but fails on a test case.
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
public class Solution {
public int pathSum(TreeNode root, int sum) {
if(root == null) return 0;
return helper(root, sum) + pathSum(root.left, sum) + pathSum(root.right, sum);
}
public int helper(TreeNode node, int sum){
if(node == null) return 0;
if(node.val == sum) return 1;
return helper(node.left, sum - node.val) + helper(node.right, sum - node.val);
}
}
In the return-statement these two recursive calls are included:
pathSum(root.right, sum) + pathSum(root.left, sum)
Complete:
return pathSum(root.left, sum - root.val) + pathSum(root.right, sum - root.val) + pathSum(root.right, sum) + pathSum(root.left, sum);
This basically means that you allow the traversal to skip nodes in the middle of the path. E.g. the path 10 -> 5 -> 3 -> -2 would be part of the solution as well, since 10 + (-2) = 8.
Now for the fix:
You need to keep track of all sums that can be found on a certain path through the tree. A way of solving this would be to keep an accumulative list of numbers:
public int pathSum(TreeNode n, Stack<Integer> acc, int sum){
if(n == null){
return 0;
}
int count = 0;
int totalToNode = acc.peek() + n.val;
//increment count, if the nodes value matches (path of length 1)
if(n.val == sum)
count++;
//increment count, if the path from root to n sums up to the given value
if(totalToNode == num)
count++;
//find all paths that end in n and sum up to the searched sum
for(int s : acc)
if(totalToNode - s == sum)
count++;
acc.push(totalToNode);
//number of matching paths for left and right subtree
count += pathSum(n.left, acc, sum);
count += pathSum(n.right, acc, sum);
acc.pop();
return count;
}
This solution represents a path as a list of values of nodes and finds all subsequences ending at the current node which sum up to a given value. This way no path will be covered twice.