I want to calculate the diameter of a binary tree for which I have made a getDiameter() function. Now in this function I need to call the findHeight() function of Binary Tree which returns the height of binary tree. The 2 functions to calculate height in code1 and code2 are little different in terms of concept.
In code1 I am considering the height of a tree with single node(only root) is 1 and in code2 I am considering the height of the tree with single node is 0. So in the base case of code1 I have returned 0 and in code2 I have returned -1. I am confused which code is correct to be used code1 or code2 because the answer of diameter will vary ....
public static int getDiameter(BinaryTreeNode root) {
if (root == null)
return 0;
int rootDiameter = findHeight(root.getLeft()) + findHeight(root.getRight()) + 1;
int leftDiameter = getDiameter(root.getLeft());
int rightDiameter = getDiameter(root.getRight());
return Math.max(rootDiameter, Math.max(leftDiameter, rightDiameter));
}
code1
public static int findHeight(BinaryTreeNode node) {
if(node == null)
return 0;
else {
return 1+Math.max(findHeight(node.left), findHeight(node.right));
}
}
Code 2
public static int findHeight(BinaryTreeNode node) {
if(node == null)
return -1;
else {
return 1+Math.max(findHeight(node.left), findHeight(node.right));
}
}
Both the concepts in code 1 and code 2 are correct to find the height of a binary tree.
The point is that you have to be consistent with the getDiameter() function for the 2 different codes.
So, if code 1 is used the getDiameter() function will be :
public static int getDiameter(BinaryTreeNode root) {
if (root == null)
return 0;
int rootDiameter = findHeight(root.getLeft()) + findHeight(root.getRight()) + 1;
int leftDiameter = getDiameter(root.getLeft());
int rightDiameter = getDiameter(root.getRight());
return Math.max(rootDiameter, Math.max(leftDiameter, rightDiameter));
}
and if code 2 is used the getDiameter() function will be :
public static int getDiameter(BinaryTreeNode root) {
if (root == null)
return 0;
int rootDiameter = findHeight(root.getLeft()) + findHeight(root.getRight()) + 3;
int leftDiameter = getDiameter(root.getLeft());
int rightDiameter = getDiameter(root.getRight());
return Math.max(rootDiameter, Math.max(leftDiameter, rightDiameter));
}
Now the answer of diameter in both the cases will be correct.....
Related
I'm looking at this question on leetcode. Given two arrays, inorder and preorder, you need to construct a binary tree. I get the general solution of the question.
Preorder traversal visits root, left, and right, so the left child would be current preorder node index + 1. From that value, you can then know how many nodes are on the left of the tree using the inorder array. In the answers, the formula used to get the right child is "preStart + inIndex - inStart + 1".
I don't want to memorize the formula so I'm wondering if there is a proof for this? I went through the discussion board there, but I'm still missing a link.
For Python Only
In Python we can also use pop(0) for solving this problem, even though that's inefficient (it would pass though).
For inefficiency we can likely use deque() with popleft(), however not on LeetCode, because we don't have control over the tree.
class Solution:
def buildTree(self, preorder, inorder):
if inorder:
index = inorder.index(preorder.pop(0))
root = TreeNode(inorder[index])
root.left = self.buildTree(preorder, inorder[:index])
root.right = self.buildTree(preorder, inorder[index + 1:])
return root
For Java and C++, that'd be a bit different just like you said (don't have the proof) but maybe this post would be just a bit helpful:
public class Solution {
public static final TreeNode buildTree(
final int[] preorder,
final int[] inorder
) {
return traverse(0, 0, inorder.length - 1, preorder, inorder);
}
private static final TreeNode traverse(
final int preStart,
final int inStart,
final int atEnd,
final int[] preorder,
final int[] inorder
) {
if (preStart > preorder.length - 1 || inStart > atEnd) {
return null;
}
TreeNode root = new TreeNode(preorder[preStart]);
int inorderIndex = 0;
for (int i = inStart; i <= atEnd; i++)
if (inorder[i] == root.val) {
inorderIndex = i;
}
root.left = traverse(preStart + 1, inStart, inorderIndex - 1, preorder, inorder);
root.right = traverse(preStart + inorderIndex - inStart + 1, inorderIndex + 1, atEnd, preorder, inorder);
return root;
}
}
C++
// The following block might slightly improve the execution time;
// Can be removed;
static const auto __optimize__ = []() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::cout.tie(nullptr);
return 0;
}();
// Most of headers are already included;
// Can be removed;
#include <cstdint>
#include <vector>
#include <unordered_map>
using ValueType = int;
static const struct Solution {
TreeNode* buildTree(
std::vector<ValueType>& preorder,
std::vector<ValueType>& inorder
) {
std::unordered_map<ValueType, ValueType> inorder_indices;
for (ValueType index = 0; index < std::size(inorder); ++index) {
inorder_indices[inorder[index]] = index;
}
return build(preorder, inorder, inorder_indices, 0, 0, std::size(inorder) - 1);
}
private:
TreeNode* build(
std::vector<ValueType>& preorder,
std::vector<ValueType>& inorder,
std::unordered_map<ValueType, ValueType>& inorder_indices,
ValueType pre_start,
ValueType in_start,
ValueType in_end
) {
if (pre_start >= std::size(preorder) || in_start > in_end) {
return nullptr;
}
TreeNode* root = new TreeNode(preorder[pre_start]);
ValueType pre_index = inorder_indices[preorder[pre_start]];
root->left = build(preorder, inorder, inorder_indices, pre_start + 1, in_start, pre_index - 1);
root->right = build(preorder, inorder, inorder_indices, pre_start + 1 + pre_index - in_start, pre_index + 1, in_end);
return root;
}
};
Is there any difference, efficiency-wise, in using instance variables vs passing arguments by function calls during recursion? For example, I was recently doing a problem on Leetcode which asked to:
Given a Binary Search Tree (BST), convert it to a Greater Tree such that every key of the original BST is changed to the original key plus sum of all keys greater than the original key in BST.
My solution and the most popular one by far is as follows: 46 ms according to Leetcode
class Solution {
public:
int sum = 0;
TreeNode* convertBST(TreeNode* root) {
if (root == NULL) return 0;
convertBST(root->right);
sum += root->val;
root->val = sum;
convertBST(root->left);
return root;
}
};
But why couldn't we also use the following solution, or does it matter? 59 ms runtime according to Leetcode
class Solution {
public:
TreeNode* convertBST(TreeNode* root, int* sum) {
if (root == NULL) return NULL;
convertBST(root->right, sum);
*sum += root->val;
root->val = *sum;
convertBST(root->left, sum);
return root;
}
TreeNode* convertBST(TreeNode* root) {
int sum = 0;
return convertBST(root, & sum);
}
};
Thanks
I have been preparing for an interview and came across this question:
Q. Build a binary tree from level order & inorder tree traversal.
Can someone guide me in this regard. I have been struggling with formulating the algorithm for long time now.
Here is the code I wrote:
struct node * buildLevelInTree(int * in, int * Level, int inStart, int inEnd, int level){
static int levelIndex=0;
struct node * root=newNode(Level[levelIndex++]);
//node has no child
if(inStart==inEnd)
return root;
int inIndex=searchIndex(in,inStart,inEnd,root->data);//search index of root in inorder traversal
//Note the use of level to take the next root from level order traversal
root->left=buildLevelInTree(in,Level,inStart,inIndex-1,2*level+1);
if(root->left!=NULL)
root->right=buildLevelInTree(in,Level,inIndex+1,inEnd,2*level+2);
else
root->right=buildLevelInTree(in,Level,inIndex+1,inEnd,2*level+1);
return root;
}//end of buildLevelInTree
Thanks a ton!
Finally, I could debug my code and work it out to function correctly. Next approach will be to optimise this algorithm. Suggestions to optimise this code (space wise) are welcomed.
/*
Algorithm Hint:
A
/ \
B C
/ \ / \
D E F G
inorder order will be DBEAFCG
and leve order will be ABCDEFG
From the level order, we know that A is the root, then check inorder, we further know DBE is left subtree and FCG is right subtree. to construct left subtree, from level order, we know left subtree's level order is BDE(find DBE's order in level order after A), we call the method to construct left subtree with inorder DBE and level order BDE.
*/
struct node * buildLevelInTree(int * in, int in_size, int *level, int l_size){
if(in_size==0 || l_size==0)
return NULL;
int in_index,l_count,r_count;
in_index=searchIndex(in,0,in_size,level[0]);
l_count=in_index;r_count=in_size-in_index-1;
struct node* root=newNode(level[0]);
int *in_left=makeInorder_left(in,in_size,in_index);
int *in_right=makeInorder_right(in,in_size,in_index);
int *level_left=makeLevel_left(level,l_size,in_left,l_count);
int *level_right=makeLevel_right(level,l_size,in_right,r_count);
root->left=buildLevelInTree(in_left,l_count,level_left,l_count);
root->right=buildLevelInTree(in_right,r_count,level_right,r_count);
return root;
}//end of buildLevelInTree
//Helping function for buildLevelInTree
int * makeInorder_right(int *in, int in_size, int pivot){
if(in==NULL)
return NULL;
int *in_right;
in_right=(int *)malloc(sizeof(int)*(in_size-pivot-1));
int i=pivot+1;
for(;i<in_size;i++)
in_right[i-pivot-1]=in[i];
return in_right;
}
//Helping function for buildLevelInTree
int *makeLevel_left(int *level, int lv_size, int * in_left, int inleft_size){
if(in_left == NULL || level == NULL)
return NULL;
int *level_left;
level_left=(int *)malloc(sizeof(int)*inleft_size);
int i=0;
int temp;
for(i=0;i<inleft_size;i++){
temp=searchLevel(level,lv_size,in_left[i]);
level_left[i]=temp;//searchLevel(level, lv_size, in_left[i]);
}
level_left=sort(level_left,inleft_size);
for(i=0;i<inleft_size;i++){
temp=level[level_left[i]];
level_left[i]=temp;//level[level_left[i]];
}
return level_left;
}
//Helping function for buildLevelInTree
int *makeLevel_right(int *level, int lv_size, int * in_right, int inright_size){
if(in_right == NULL || level == NULL)
return NULL;
int *level_right;
level_right=(int *)malloc(sizeof(int)*inright_size);
int i=0;
for(i=0;i<inright_size;i++)
level_right[i]=searchLevel(level, lv_size, in_right[i]);
level_right=sort(level_right,inright_size);
for(i=0;i<inright_size;i++)
level_right[i]=level[level_right[i]];
return level_right;
}
//Helping function for buildLevelInTree
int * sort(int *a,int n)
{
int i,j,k,temp;
for(i=1;i< n;i++)
{
for(j=0;j< n-1;j++)
if(a[j]>a[j+1])
{
temp=a[j];
a[j]=a[j+1];
a[j+1]=temp;
}
}
return a;
}
//Helping function for buildLevelInTree
int searchLevel(int *level, int lv_size, int value){
int i=0;
for(i=0;i<lv_size;i++){
if(level[i]==value)
return i;
}
return -1;
}
I am trying to implement a function to calculate path length of a binary tree and i am not able to get the correct answer. Can you check what i am doing wrong? Here is my code below:
public int pathLength() {
int sum = 0;
int c = 1;
pathLength(root, sum);
return sum;
}
public int pathLength(Node n, int sum) {
if(n.isRoot())
sum+= 0;
if(n.left == null && n.right == null)
return;
c++;
if(n.left != null)
sum += c;
if (n.right != null)
sum+=c;
pathLength(n.left, sum);
pathLength(n.right, sum);
}
There are a lot of things wrong with this code. It wouldn't even compile because a) In the 2nd function c is never declared (it is local in the first) and b) the 2nd function never returns a value.
But the biggest issue is the way you declare the 2nd function. "sum" is passed by value. That basically means a new copy of "sum" is created each time you call the function and is discarded when the function ends.
What you want to do is pass by reference. When doing this, the actual sum variable, not a copy, is passed to the function. So your code might look like this:
public void pathLength(Node n, int& sum) {
//if(n.isRoot()) <- not sure what this is for
// sum+= 0;
sum += 1; // Increment for this node
//if(n.left == null && n.right == null)
// return; // This conditional is not needed with next 2 if statements
//c++; <- Don't know what c is for
// Recursively call for child nodes
if(n.left != null)
pathLength(n.left, sum);
if (n.right != null)
pathLength(n.right, sum);
}
Note that this counts all the nodes in the tree. I assume that's what you want. If you want to find the deepest node, that's different.
Is it because of you set the initial value of c as 1 instead of 0?
The children of root should be at level 2 with the depth 1.
Here is an easy approach
Time : O(n) while the space will be O(h) where h is the height of the binary tree:
int sum(BinaryTree *node, int count){
if(node == nullptr){
return 0;
}
return count + sum(node->left, count+1)+sum(node->right, count+1);
}
int nodeDepths(BinaryTree *root) {
int count=0;
int ans=0;
ans =sum(root, count);
return ans;
}
I have a list of nodes, where each of the nodes belong to one or multiple trees. (they do not necessarily share a common ancestor)
I want to sort the nodes in the same order I would find them when doing a Depth First Search.
Let say I have a predicate for sorting tree roots together, and another predicate to sort children of a common parent together. Each node have a Parent accessor, and a children enumerator. I want to avoid using the Children enumeration for performance reasons (if possible).
What can be the pseudo code for a predicate to pass to a sort function (the predicate would return a boolean value if node 1 is less than node 2).
I think, you need to store helpful information in nodes, so predicate can choose preceding node from pair of unconnected nodes.
Here's my (may be not very clever or, even, working) attempt:
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
*
*/
public class SortingTree {
private static class Node implements Comparable<Node> {
private final String data;
private Node p, l, r;
private int ordinal = 0;
public Node(String data) {
this.data = data;
}
public Node setLeft(Node n) {
n.ordinal = ordinal + 1;
if (ordinal == 0)
n.ordinal = 2;
else
n.ordinal = ordinal + 2;
n.p = this;
return n;
}
public Node setRight(Node n) {
if (ordinal == 0)
n.ordinal = 1;
else
n.ordinal = ordinal + 4;
n.p = this;
return n;
}
public String toString() {
return data;
}
public int compareTo(Node o) {
// check if one of args is root
if (p == null && o.p != null) return -1;
if (p != null && o.p == null) return 1;
if (p == null && o.p == null) return 0;
// check if one of args is left subtree, while other is right
if (ordinal % 2 == 0 && o.ordinal % 2 == 1) return -1;
if (ordinal % 2 == 1 && o.ordinal % 2 == 0) return 1;
// if ordinals are the same, first element is the one which parent have bigger ordinal
if (ordinal == o.ordinal) {
return o.p.ordinal - p.ordinal;
}
return ordinal - o.ordinal;
}
}
public static void main(String[] args) {
List<Node> nodes = new ArrayList<Node>();
Node root = new Node("root"); nodes.add(root);
Node left = root.setLeft(new Node("A")); nodes.add(left);
Node leftLeft = left.setLeft(new Node("C")); nodes.add(leftLeft); nodes.add(leftLeft.setLeft(new Node("D")));
nodes.add(left.setRight(new Node("E")));
Node right = root.setRight(new Node("B")); nodes.add(right);
nodes.add(right.setLeft(new Node("F"))); nodes.add(right.setRight(new Node("G")));
Collections.sort(nodes);
System.out.println(nodes);
}
}
I found an easy working solution:
For a node, have a function that returns the path from the root. For example, in a file system, the path for a file could be : c:\directory\file.txt, where "C:", "directory" and "file.txt" are the parent nodes.
The predicate simply need to compare the paths together, as a simple string comparison would do. The path does not need to be a string, the path comparison function need to compare path elements one by one starting at the root, and return as soon a path element is different.
The resulting sort is the same as a Depth First Search.