I have written a code for finding least common ancestor of nodes in binary tree but it seems to return null instead of the LCA.
My algorithm is as below.
Recursively find the ancestor in left and right branch of tree
A node where left as well as right tree has matching elements in the LCA.
public class LCA {
public static BinaryTreeNode findLCA( BinaryTreeNode root, BinaryTreeNode node1 , BinaryTreeNode node2) {
if (root == null) {
return null;
}
BinaryTreeNode left = root.getLeft();
BinaryTreeNode right = root.getRight();
if (left != null && (left == node1 || left == node2)) {
return root;
}
if (right != null && (right == node1 || right == node2)) {
return root;
}
if (( findLCA(left, node1, node2) != null) && (findLCA(right, node1, node2) != null)) {
return root;
}
return null; }}
What could be the problem with this code?
I think I am able to fix it. I added another condition to see if my recursive findLCA is returning something. If so I return the same value further which fixed the issue. Plz provide your comments if this design is ok.
public static BinaryTreeNode findLCA( BinaryTreeNode root, BinaryTreeNode node1 , BinaryTreeNode node2) {
if (root == null) {
return null;
}
BinaryTreeNode left = root.getLeft();
BinaryTreeNode right = root.getRight();
BinaryTreeNode lcaNode1;
BinaryTreeNode lcaNode2;
if (left != null && (left == node1 || left == node2)) {
return root;
}
if (right != null && (right == node1 || right == node2)) {
return root;
}
lcaNode1 = findLCA(left, node1, node2);
lcaNode2 = findLCA(right, node1, node2);
if (( lcaNode1 != null) && lcaNode2 != null) {
return root;
}
if (lcaNode1 != null) {
return lcaNode1;
}
if (lcaNode2 != null) {
return lcaNode2;
}
return null;
}
Related
I wrote the following code for finding the height of the binary tree, this is wrong, its failing the test cases, but why it is wrong, how to prove logically that this is wrong?
// WRONG CODE
public static int height(Node root) {
if(root != null){
if(root.left != null && root.right != null){
return Math.max(height(root.left), height(root.right)) + 1;
}else if(root.left != null){
return height(root.left);
}else{
return height(root.right);
}
}
return 0;
}
Whereas this following code is right!!
//RIGHT WORKING CODE
public static int height(Node root) {
if(root != null){
if(root.left != null || root.right != null){
return Math.max(height(root.left), height(root.right)) + 1;
}
}
return 0;
}
What is the big difference between the two codes that makes one of them right and other the wrong one?
For clarity the class code for the Node is added here.
class Node {
Node left;
Node right;
int data;
Node(int data) {
this.data = data;
left = null;
right = null;
}
}
And this is the logic to insert a node into the binary tree.
public static Node insert(Node root, int data) {
if(root == null) {
return new Node(data);
} else {
Node cur;
if(data <= root.data) {
cur = insert(root.left, data);
root.left = cur;
} else {
cur = insert(root.right, data);
root.right = cur;
}
return root;
}
In the second and third cases (just a left node, or just a right node) you're not adding one to account for the node you're currently on.
By the way your code also has a potential bug, in that it's possible for both left and right to be null. Your height function can handle null so really none of this checking is necessary, except for the check on the first line of the height function itself. But if it's important to check for null in the second case, then you should check for null in the third case too.
I'm attempting to write a method that would remove node from BST by the given value and I need it to return this deleted value. I found assorted examples of recursive implementations, but because of their nature, they can't return deleted node, but rather the root. Here's what I have now
public TreeNode remove(TreeNode node, int data) {
if (null == node) {
return null;
}
if (data < node.st.getkey()) {
node.left = remove(node.left, data);
} else if (data > node.st.getkey()) {
node.right = remove(node.right, data);
} else { // case for equality
if (node.left != null && node.right != null) {
TreeNode minInRightSubTree = min(node.right);
copyData(node , minInRightSubTree);
node.right = remove(node.right, minInRightSubTree.st.getkey());
} else {
if (node.left == null && node.right == null) {
node = null;
} else {// one child case
TreeNode deleteNode = node;
node = (node.left != null) ? (node.left) : (node.right);
deleteNode = null;
}
}
}
return node;
}
Can I come up with some hack to make it return deleted node or should I look into iterative algorithm( and if so I would really appreciate it if you could hook me up with the link).
You can return not just root but a pair of root and deleted node (or null if nothing was deleted).
You can use Map.Entry or new class to store 2 fields (I would recommend new class since it's more descriptive).
So your possible new signature will be public Map.Entry<TreeNode, TreeNode> remove(TreeNode node, int data)
Here's a method header but I'm really confused
public TreeNode find(Treenode Target){
}
Heres something I was trying. Can anyone critique, fix this
public TreeNode find(Treenode Target){
treeNode targ = null;
if(this.getdata == target)
return this;
if(left != null)
targ = left.find(target);
if(right != null)
targ = right.find(target);
return targ;
}
You should check what the recursive search returns, something like:
public TreeNode find(Treenode Target){
treeNode targ = null;
if(this.getdata == target)
return this;
if(left != null) {
targ = left.find(target);
if (targ!=null)
return targ;
}
if(right != null)
targ = right.find(target);
if (targ!=null)
return targ;
}
return null;
}
You can spare the last if and return targ an the end, but I think this is more understandable.
Your attempt should stop the recursing at the point a target is found. In your formulation, even if the target is found on the left, it will continue recursing down the right. Your pseudocode syntax is a little jarbled, but if I follow the gist:
public TreeNode find (TreeNode target) {
TreeNode targ = null;
if (getdata() == target.getdata())
return this;
if (left() != null)
targ = left().find(target);
if (targ == null && right() != null)
targ = right().find(target);
return targ;
}
If your binary tree is organized as a binary search tree, you can avoid the exhaustive search of the data structure, and only follow the side that would contain your item if the item is in your tree.
public TreeNode find (TreeNode target) {
TreeNode next;
if (getdata() == target.getdata())
return this;
if (getdata() < target.getdata())
next = left();
else
next = right();
return (next != null)
? next.find(target)
: null;
}
Following is your code shortened:
public TreeNode find(Treenode target) {
TreeNode targ = null;
if(this.getdata == target) return this;
if(left != null) targ = left.find(target);
if(right != null) targ = right.find(target);
return targ;
}
Your code will fail in the case when the target is in the left subtree because you are not checking the value returned from the call left.find(target). The variable targ may have a valid value after that call but it will get overwritten by the call to right.find(target) which you make when right subtree is not empty.
The correct code can be:
public TreeNode find(Treenode target) {
if(this == target) return this; //return if I'm the node being searched
TreeNode targ = null;
if(left != null) targ = left.find(target); //first search in my left subtree
if(targ != null) return targ; //if found in my left subtree, return the node
if(right != null) targ = right.find(target); //search in my right subtree
return targ; //just return - whether null or a valid node
}
I am doing an assignment, implementing own Binary Search Tree. The thing is, we have our own implementation of Node its parent is not directly accessible.
I have searched for answers, but I do not want to copy the solution entirely and I still don't seem to get it right, though. I miss some cases when the element is not removed.
Can you please help what am I doing wrong?
This is the remove method:
void remove(E elem) {
if(elem != null){
if (root != null && contains(elem)) {
removeFromSubtree(elem, root, null);
}
}
}
void removeFromSubtree(E elem, Node<E> current, Node<E> parent) {
if(elem.less(current.contents)){
if(current.left == null) return ;
removeFromSubtree(elem, current.left, current);
} else if(elem.greater(current.contents)){
if(current.right == null)return;
removeFromSubtree(elem, current.right, current);
} else {
if(current.left != null && current.right != null){
//both children
if(parent == null){
Node<E> n = new Node<>(null, null);
n.left = root;
removeFromSubtree(root.contents, n, null);
root = n.left;
root.setParent(null);
}
E min = subtreeMin(current.right);
current.contents = min;
removeFromSubtree(min, current.right, current);
} else if(current.left != null){
//left child
if (parent == null) {
root = current.left;
current.left.setParent(null);
return ;
}
setParentChild(current, parent, current.left);
} else if(current.right != null){
//right child
if (parent == null) {
root = current.right;
current.right.setParent(null);
return ;
}
setParentChild(current, parent, current.right);
} else {
if (parent == null) {
root = null;
return ;
}
setParentChild(current, parent, null);
}
}
}
Nodes use generic interface
class Node<E extends DSAComparable<E>>
which has just methods for comparation. It looks like this
interface DSAComparable<E extends DSAComparable<E>> {
boolean less(E other);
boolean greater(E other);
boolean equal(E other);
}
I use another methon inside remove that sets node's parent's child, depending if its left child or right child.
void setParentChild(Node<E> node, Node<E> parent,Node<E> value){
if(parent!= null){
if (parent.left == node) {
parent.left = value;
} else {
parent.right = value;
}
if(value!= null) value.setParent(parent);
}
}
Method subtreeMin(Node node) finds the smallest value in a subtree (the most left one)
Understanding your code is not so easy, since it still lacks of details.
I would refer to such an implementation of the Binary Search Tree that you can find online.
See for instance the one from Algorithms, 4th Ed..
I am posting new question with my code. I am trying to count the non-leaf nodes of a binary search tree. I am creating the non-leaf method and then I am trying to call it in a test class. Can someone help me? Here is the code:
public class BST {
private Node<Integer> root;
public BST() {
root = null;
}
public boolean insert(Integer i) {
Node<Integer> parent = root, child = root;
boolean gLeft = false;
while (child != null && i.compareTo(child.data) != 0) {
parent = child;
if (i.compareTo(child.data) < 0) {
child = child.left;
gLeft = true;
} else {
child = child.right;
gLeft = false;
}
}
if (child != null)
return false;
else {
Node<Integer> leaf = new Node<Integer>(i);
if (parent == null)
root = leaf;
else if (gLeft)
parent.left = leaf;
else
parent.right = leaf;
return true;
}
}
public boolean find(Integer i) {
Node<Integer> n = root;
boolean found = false;
while (n != null && !found) {
int comp = i.compareTo(n.data);
if (comp == 0)
found = true;
else if (comp < 0)
n = n.left;
else
n = n.right;
}
return found;
}
public int nonleaf() {
int count = 0;
Node<Integer> parent = root;
if (parent == null)
return 0;
if (parent.left == null && parent.right == null)
return 1;
}
}
class Node<T> {
T data;
Node<T> left, right;
Node(T o) {
data = o;
left = right = null;
}
}
If you are interested in only count of non-leaf node then you can traverse tree once and maintain one count. whenever you encounter a node such that it has either left or right node increment count.
You can use the following function to count number of non-leaf nodes of binary tree.
int countNonLeafNodes(Node root)
{
if (root == null || (root.left == null &&
root.right == null))
return 0;
return 1 + countNonLeafNodes(root.left) +
countNonLeafNodes(root.right);
}