LCA of Binary Tree - Need some Advice - java

I know this question has been asked many times. I need some clarification on LCA of a Binary Tree (not BST). If I am trying to find LCA of two nodes(3,11) from the given tree :
_______1______
/ \
___2__ ___4__
/ \ / \
6 5 9 11
/ \
7 3
The Code returns 11 for (3,11).
// Binary Tree LCA not BST
private Node findLowestCommonAncestor(Node root, int value1, int value2) {
Node leftLCA = null;
Node rightLCA = null;
if (root == null) {
return null;
}
else {
int value = root.item;
if (value == value1 || value == value2) {
return root;
}
else {
leftLCA = findLowestCommonAncestor(root.left, value1, value2);
rightLCA = findLowestCommonAncestor(root.right, value1, value2);
if (leftLCA != null && rightLCA != null) {
return root;
}
return (leftLCA != null) ? leftLCA : rightLCA;
}
}
}
Here I am confused, It should be 4 right. Please correct me If I am wrong. Am I confusing here ? or Is it how LCA works ?

11 is the correct LCA of (3, 11) in the tree you've shown.
I think you've perhaps overlooked the bit in the definition of LCA where elements are considered descendants of themselves:
...the lowest common ancestor (LCA) of two nodes v and w in a tree or directed acyclic graph (DAG) is the lowest (i.e. deepest) node that has both v and w as descendants, where we define each node to be a descendant of itself (so if v has a direct connection from w, w is the lowest common ancestor).
(emphasis mine)
Since 3 is a child of 11, the LCA is 11.

Related

Validate a Binary Search Tree

I am working on a leetcode problem where I am asked to check whether or not a Binary Search Tree is valid. So far, my solution only passes 58 out 75 test cases. Any pointers on where I went wrong and how to fix it?
Here is the question:
Given a binary tree, determine if it is a valid binary search tree (BST).
Assume a BST is defined as follows:
The left subtree of a node contains only nodes with keys less than the node's key.
The right subtree of a node contains only nodes with keys greater than the node's key.
Both the left and right subtrees must also be binary search trees.
Example 1:
2
/ \
1 3
Input: [2,1,3]
Output: true
Example 2:
5
/ \
1 4
/ \
3 6
Input: [5,1,4,null,null,3,6]
Output: false
Explanation: The root node's value is 5 but its right child's value is 4.
Here is my Solution:
class Solution {
public boolean isValidBST(TreeNode root) {
return isValidHelper(root);
}
public boolean isValidHelper(TreeNode root)
{
if(root == null)
return true;
isValidHelper(root.left);
if(root.left != null && !(root.left.val < root.val) || root.right != null && !(root.right.val > root.val))
return false;
isValidHelper(root.right);
return true;
}
}
Your program fails in cases like this:
5
3 7
1 6
because you only compare the value at the root of the subtrees.
I don't give a fix on purpose. You will learn more finding that out yourself.

How does it ensure that one node is an ancestor and not a sibling?

I am trying to solve this LeetCode question:
Given the root of a binary tree, find the maximum value V for which there exists different nodes A and B where V = |A.val - B.val| and A is an ancestor of B. (A node A is an ancestor of B if either: any child of A is equal to B, or any child of A is an ancestor of B.)
One of the highly upvoted answers is as below:
public int maxAncestorDiff(TreeNode root) {
return dfs(root, root.val, root.val);
}
public int dfs(TreeNode root, int mn, int mx) {
if (root == null) return mx - mn;
mx = Math.max(mx, root.val);
mn = Math.min(mn, root.val);
return Math.max(dfs(root.left, mn, mx), dfs(root.right, mn, mx));
}
This is basically just a preorder traversal of the tree. I am unable to digest how it ensures that node A is an ancestor of node B (and not a sibling)?
Let's break this down.
You are correct that this is just a pre-order transversal. What's important is that for each node we have a minimum value and a maximum value. These values get smaller and larger respectively as we iterate down the tree. At any one given node, we only update mn and mx with the value of that node. As a result when we pass mn and mx to the children, those values are only reflective of nodes in the tree up to the current node.
Perhaps these comments will illustrate this better:
public int dfs(TreeNode root, int mn, int mx) {
// this is the base case, at some point mn was encountered and mx was encountered
// on the path to this node, this is the maximum possible difference along that path
if (root == null) return mx - mn;
// on our current path through the tree, update the max / min value we have encountered
mx = Math.max(mx, root.val);
mn = Math.min(mn, root.val);
// the mn and mx at this point are only reflective of this node and it's ancestors
// integers are immutable so a function call down the line won't change the
// mx and mn here, but rather create a new mx and mn at that node
// we pass the updated mx and mn to the node's children, exploring paths
// down the tree
return Math.max(dfs(root.left, mn, mx), dfs(root.right, mn, mx));
}

convert binary tree to sum tree in Java

REFERENCE I am copy pasting the problem and the solution that works in C, I am not able to get this working in Java. I understand primarily it is because in Java parameters are passed by value and that is causing problem to maintain state of "old_value". But I even tried changing it to a custom MyInt with set and get, still not able to get this working. So, probably I am missing something else too here. Kindly suggest.
Given a Binary Tree where each node has positive and negative values.
Convert this to a tree where each node contains the sum of the left
and right sub trees in the original tree. The values of leaf nodes are
changed to 0.
For example, the following tree
10
/ \
-2 6
/ \ / \
8 -4 7 5
should be changed to
20(4-2+12+6)
/ \
4(8-4) 12(7+5)
/ \ / \
0 0 0 0
Code:
int toSumTree(struct node *node)
{
// Base case
if(node == NULL)
return 0;
// Store the old value
int old_val = node->data;
// Recursively call for left and right subtrees and store the sum as
// new value of this node
node->data = toSumTree(node->left) + toSumTree(node->right);
// Return the sum of values of nodes in left and right subtrees and
// old_value of this node
return node->data + old_val;
}
Java Code:
public static int sumTree(Node node){
if(node == null)
return 0;
MyInt old_value = new MyInt(node.data);
node.data = sumTree(node.left) + sumTree(node.right);
return node.data + old_value.getData();
}
I was running wrong tests. Same code logic will work in Java as well as rightly pointed out in comments that pass by value does not make a difference because value is getting returned. The following is the working Java Code:
public static int sumTree(TreeNode node){
if(node == null)
return 0;
int old_value = node.value;
node.value = sumTree(node.left) + sumTree(node.right);
return node.value + old_value;
}

How is this program a pre-order traversal?

int count(Node node) {
if (node == null)
return 0;
int r = count (node.right);
int l = count (node.left);
return 1 + r + l;
}
This function returns number of nodes in Binary Tree rooted at node. A few articles say this is a pre-order traversal, but to me this looks like a post-order traversal, because we are visiting the left and the right parts before we visit the root. Am I wrong here ? Or is my notion of "visited" at fault ?
In this code, no actual processing is being done at each node, so there would be no difference between a pre-order and post-order traversal. If there were processing, the difference would be:
pre-order
int count(Node node) {
if (node == null)
return 0;
process(node);
int r = count (node.right);
int l = count (node.left);
return 1 + r + l;
}
post-order
int count(Node node) {
if (node == null)
return 0;
int r = count (node.right);
int l = count (node.left);
process(node);
return 1 + r + l;
}
(Actually, in these cases—unlike with your code—you'd probably want to recurse on node.left before node.right to preserve the conventional left-to-right ordering of processing children.)
Counting nodes is case in which it is hard to say if algorithm is pre-order or is post-order because we don't know "when" we "count" 1 for current node.
But if we change case to printing it becomes clear:
pre-order:
int visit(Node node) {
...
node.print(); // pre-order : root cames first
visit(node.left);
visit(node.right);
...
}
post-order
int visit(Node node) {
...
visit(node.left);
visit(node.right);
node.print(); // post-order : root cames last
...
}
As you can see we can say which print() comes first.
With counting we cannot say if root is counted (+1) prior to subtrees or not.
This is question of convention.
We could say this is pre-order traversal as the count function is applied to a node before than to its children.
But the question is rather tricky as you are using direct recursion, doing both the traversal and the "action" in the same function.
Yes. Your notion of visited is wrong! Here visited means that you are at current node and then trying to traverse the tree. Counting is done at 'root' first then ur counting rights and then lefts so yes it is preorder.

Insert into binary tree without sorting input

how can you build binary tree without sorting it, I.E
if i have a input 5 4 9 8 1 2 7 how can you insert that into a reference based binary tree.
I know this can be easily implemented with Array, but is it possible with reference base?
Tree buildTree(int[] array, int index) {
if(index > array.length) { return null; }
return new Tree(
array[index],
buildTree(array, 2 * index + 1),
buildTree(array, 2 * index + 2));
}
Most of the work is in the recursion and in the indexing, but it's not too bad at all.
One simple rule is to always insert into the left subtree and then switch the subtrees. The right subtree will always be 0-1 elements larger than the left subtree, so you can always insert into the left subtree. Now, the left subtree is 0-1 elements larger than the right subtree, so you want to switch the subtrees to preserve the invariant. In pseudocode:
insert(t,v) {
if (t == null) {
return new TreeNode(v,null,null)
} else {
left = insert(t.left,v)
right = t.right
t.left = right
t.right = left
return t
}
}

Categories