Find kth smallest element in a binary search tree in Optimum way - algorithm
I need to find the kth smallest element in the binary search tree without using any static/global variable. How to achieve it efficiently?
The solution that I have in my mind is doing the operation in O(n), the worst case since I am planning to do an inorder traversal of the entire tree. But deep down I feel that I am not using the BST property here. Is my assumptive solution correct or is there a better one available ?
Here's just an outline of the idea:
In a BST, the left subtree of node T contains only elements smaller than the value stored in T. If k is smaller than the number of elements in the left subtree, the kth smallest element must belong to the left subtree. Otherwise, if k is larger, then the kth smallest element is in the right subtree.
We can augment the BST to have each node in it store the number of elements in its left subtree (assume that the left subtree of a given node includes that node). With this piece of information, it is simple to traverse the tree by repeatedly asking for the number of elements in the left subtree, to decide whether to do recurse into the left or right subtree.
Now, suppose we are at node T:
If k == num_elements(left subtree of T), then the answer we're looking for is the value in node T.
If k > num_elements(left subtree of T), then obviously we can ignore the left subtree, because those elements will also be smaller than the kth smallest. So, we reduce the problem to finding the k - num_elements(left subtree of T) smallest element of the right subtree.
If k < num_elements(left subtree of T), then the kth smallest is somewhere in the left subtree, so we reduce the problem to finding the kth smallest element in the left subtree.
Complexity analysis:
This takes O(depth of node) time, which is O(log n) in the worst case on a balanced BST, or O(log n) on average for a random BST.
A BST requires O(n) storage, and it takes another O(n) to store the information about the number of elements. All BST operations take O(depth of node) time, and it takes O(depth of node) extra time to maintain the "number of elements" information for insertion, deletion or rotation of nodes. Therefore, storing information about the number of elements in the left subtree keeps the space and time complexity of a BST.
A simpler solution would be to do an inorder traversal and keep track of the element currently to be printed (without printing it). When we reach k, print the element and skip rest of tree traversal.
void findK(Node* p, int* k) {
if(!p || k < 0) return;
findK(p->left, k);
--k;
if(k == 0) {
print p->data;
return;
}
findK(p->right, k);
}
public int ReturnKthSmallestElement1(int k)
{
Node node = Root;
int count = k;
int sizeOfLeftSubtree = 0;
while(node != null)
{
sizeOfLeftSubtree = node.SizeOfLeftSubtree();
if (sizeOfLeftSubtree + 1 == count)
return node.Value;
else if (sizeOfLeftSubtree < count)
{
node = node.Right;
count -= sizeOfLeftSubtree+1;
}
else
{
node = node.Left;
}
}
return -1;
}
this is my implementation in C# based on the algorithm above just thought I'd post it so people can understand better it works for me
thank you IVlad
//add a java version without recursion
public static <T> void find(TreeNode<T> node, int num){
Stack<TreeNode<T>> stack = new Stack<TreeNode<T>>();
TreeNode<T> current = node;
int tmp = num;
while(stack.size() > 0 || current!=null){
if(current!= null){
stack.add(current);
current = current.getLeft();
}else{
current = stack.pop();
tmp--;
if(tmp == 0){
System.out.println(current.getValue());
return;
}
current = current.getRight();
}
}
}
A simpler solution would be to do an inorder traversal and keep track of the element currently to be printed with a counter k. When we reach k, print the element. The runtime is O(n). Remember the function return type can not be void, it has to return its updated value of k after each recursive call. A better solution to this would be an augmented BST with a sorted position value at each node.
public static int kthSmallest (Node pivot, int k){
if(pivot == null )
return k;
k = kthSmallest(pivot.left, k);
k--;
if(k == 0){
System.out.println(pivot.value);
}
k = kthSmallest(pivot.right, k);
return k;
}
You can use iterative inorder traversal:
http://en.wikipedia.org/wiki/Tree_traversal#Iterative_Traversal
with a simple check for kth element after poping a node out of the stack.
Given just a plain binary search tree, about all you can do is start from the smallest, and traverse upward to find the right node.
If you're going to do this very often, you can add an attribute to each node signifying how many nodes are in its left sub-tree. Using that, you can descend the tree directly to the correct node.
Recursive In-order Walk with a counter
Time Complexity: O( N ), N is the number of nodes
Space Complexity: O( 1 ), excluding the function call stack
The idea is similar to #prasadvk solution, but it has some shortcomings (see notes below), so I am posting this as a separate answer.
// Private Helper Macro
#define testAndReturn( k, counter, result ) \
do { if( (counter == k) && (result == -1) ) { \
result = pn->key_; \
return; \
} } while( 0 )
// Private Helper Function
static void findKthSmallest(
BstNode const * pn, int const k, int & counter, int & result ) {
if( ! pn ) return;
findKthSmallest( pn->left_, k, counter, result );
testAndReturn( k, counter, result );
counter += 1;
testAndReturn( k, counter, result );
findKthSmallest( pn->right_, k, counter, result );
testAndReturn( k, counter, result );
}
// Public API function
void findKthSmallest( Bst const * pt, int const k ) {
int counter = 0;
int result = -1; // -1 := not found
findKthSmallest( pt->root_, k, counter, result );
printf("%d-th element: element = %d\n", k, result );
}
Notes (and differences from #prasadvk's solution):
if( counter == k ) test is required at three places: (a) after left-subtree, (b) after root, and (c) after right subtree. This is to ensure that kth element is detected for all locations, i.e. irrespective of the subtree it is located.
if( result == -1 ) test required to ensure only the result element is printed, otherwise all the elements starting from the kth smallest up to the root are printed.
For not balanced searching tree, it takes O(n).
For balanced searching tree, it takes O(k + log n) in the worst case but just O(k) in Amortized sense.
Having and managing the extra integer for every node: the size of the sub-tree gives O(log n) time complexity.
Such balanced searching tree is usually called RankTree.
In general, there are solutions (based not on tree).
Regards.
This works well: status : is the array which holds whether element is found. k : is kth element to be found. count : keeps track of number of nodes traversed during the tree traversal.
int kth(struct tree* node, int* status, int k, int count)
{
if (!node) return count;
count = kth(node->lft, status, k, count);
if( status[1] ) return status[0];
if (count == k) {
status[0] = node->val;
status[1] = 1;
return status[0];
}
count = kth(node->rgt, status, k, count+1);
if( status[1] ) return status[0];
return count;
}
While this is definitely not the optimal solution to the problem, it is another potential solution which I thought some people might find interesting:
/**
* Treat the bst as a sorted list in descending order and find the element
* in position k.
*
* Time complexity BigO ( n^2 )
*
* 2n + sum( 1 * n/2 + 2 * n/4 + ... ( 2^n-1) * n/n ) =
* 2n + sigma a=1 to n ( (2^(a-1)) * n / 2^a ) = 2n + n(n-1)/4
*
* #param t The root of the binary search tree.
* #param k The position of the element to find.
* #return The value of the element at position k.
*/
public static int kElement2( Node t, int k ) {
int treeSize = sizeOfTree( t );
return kElement2( t, k, treeSize, 0 ).intValue();
}
/**
* Find the value at position k in the bst by doing an in-order traversal
* of the tree and mapping the ascending order index to the descending order
* index.
*
*
* #param t Root of the bst to search in.
* #param k Index of the element being searched for.
* #param treeSize Size of the entire bst.
* #param count The number of node already visited.
* #return Either the value of the kth node, or Double.POSITIVE_INFINITY if
* not found in this sub-tree.
*/
private static Double kElement2( Node t, int k, int treeSize, int count ) {
// Double.POSITIVE_INFINITY is a marker value indicating that the kth
// element wasn't found in this sub-tree.
if ( t == null )
return Double.POSITIVE_INFINITY;
Double kea = kElement2( t.getLeftSon(), k, treeSize, count );
if ( kea != Double.POSITIVE_INFINITY )
return kea;
// The index of the current node.
count += 1 + sizeOfTree( t.getLeftSon() );
// Given any index from the ascending in order traversal of the bst,
// treeSize + 1 - index gives the
// corresponding index in the descending order list.
if ( ( treeSize + 1 - count ) == k )
return (double)t.getNumber();
return kElement2( t.getRightSon(), k, treeSize, count );
}
signature:
Node * find(Node* tree, int *n, int k);
call as:
*n = 0;
kthNode = find(root, n, k);
definition:
Node * find ( Node * tree, int *n, int k)
{
Node *temp = NULL;
if (tree->left && *n<k)
temp = find(tree->left, n, k);
*n++;
if(*n==k)
temp = root;
if (tree->right && *n<k)
temp = find(tree->right, n, k);
return temp;
}
Well here is my 2 cents...
int numBSTnodes(const Node* pNode){
if(pNode == NULL) return 0;
return (numBSTnodes(pNode->left)+numBSTnodes(pNode->right)+1);
}
//This function will find Kth smallest element
Node* findKthSmallestBSTelement(Node* root, int k){
Node* pTrav = root;
while(k > 0){
int numNodes = numBSTnodes(pTrav->left);
if(numNodes >= k){
pTrav = pTrav->left;
}
else{
//subtract left tree nodes and root count from 'k'
k -= (numBSTnodes(pTrav->left) + 1);
if(k == 0) return pTrav;
pTrav = pTrav->right;
}
return NULL;
}
This is what I though and it works. It will run in o(log n )
public static int FindkThSmallestElemet(Node root, int k)
{
int count = 0;
Node current = root;
while (current != null)
{
count++;
current = current.left;
}
current = root;
while (current != null)
{
if (count == k)
return current.data;
else
{
current = current.left;
count--;
}
}
return -1;
} // end of function FindkThSmallestElemet
Well we can simply use the in order traversal and push the visited element onto a stack.
pop k number of times, to get the answer.
we can also stop after k elements
Solution for complete BST case :-
Node kSmallest(Node root, int k) {
int i = root.size(); // 2^height - 1, single node is height = 1;
Node result = root;
while (i - 1 > k) {
i = (i-1)/2; // size of left subtree
if (k < i) {
result = result.left;
} else {
result = result.right;
k -= i;
}
}
return i-1==k ? result: null;
}
The Linux Kernel has an excellent augmented red-black tree data structure that supports rank-based operations in O(log n) in linux/lib/rbtree.c.
A very crude Java port can also be found at http://code.google.com/p/refolding/source/browse/trunk/core/src/main/java/it/unibo/refolding/alg/RbTree.java, together with RbRoot.java and RbNode.java. The n'th element can be obtained by calling RbNode.nth(RbNode node, int n), passing in the root of the tree.
Here's a concise version in C# that returns the k-th smallest element, but requires passing k in as a ref argument (it's the same approach as #prasadvk):
Node FindSmall(Node root, ref int k)
{
if (root == null || k < 1)
return null;
Node node = FindSmall(root.LeftChild, ref k);
if (node != null)
return node;
if (--k == 0)
return node ?? root;
return FindSmall(root.RightChild, ref k);
}
It's O(log n) to find the smallest node, and then O(k) to traverse to k-th node, so it's O(k + log n).
http://www.geeksforgeeks.org/archives/10379
this is the exact answer to this question:-
1.using inorder traversal on O(n) time
2.using Augmented tree in k+log n time
I couldn't find a better algorithm..so decided to write one :)
Correct me if this is wrong.
class KthLargestBST{
protected static int findKthSmallest(BSTNode root,int k){//user calls this function
int [] result=findKthSmallest(root,k,0);//I call another function inside
return result[1];
}
private static int[] findKthSmallest(BSTNode root,int k,int count){//returns result[]2 array containing count in rval[0] and desired element in rval[1] position.
if(root==null){
int[] i=new int[2];
i[0]=-1;
i[1]=-1;
return i;
}else{
int rval[]=new int[2];
int temp[]=new int[2];
rval=findKthSmallest(root.leftChild,k,count);
if(rval[0]!=-1){
count=rval[0];
}
count++;
if(count==k){
rval[1]=root.data;
}
temp=findKthSmallest(root.rightChild,k,(count));
if(temp[0]!=-1){
count=temp[0];
}
if(temp[1]!=-1){
rval[1]=temp[1];
}
rval[0]=count;
return rval;
}
}
public static void main(String args[]){
BinarySearchTree bst=new BinarySearchTree();
bst.insert(6);
bst.insert(8);
bst.insert(7);
bst.insert(4);
bst.insert(3);
bst.insert(4);
bst.insert(1);
bst.insert(12);
bst.insert(18);
bst.insert(15);
bst.insert(16);
bst.inOrderTraversal();
System.out.println();
System.out.println(findKthSmallest(bst.root,11));
}
}
Here is the java code,
max(Node root, int k) - to find kth largest
min(Node root, int k) - to find kth Smallest
static int count(Node root){
if(root == null)
return 0;
else
return count(root.left) + count(root.right) +1;
}
static int max(Node root, int k) {
if(root == null)
return -1;
int right= count(root.right);
if(k == right+1)
return root.data;
else if(right < k)
return max(root.left, k-right-1);
else return max(root.right, k);
}
static int min(Node root, int k) {
if (root==null)
return -1;
int left= count(root.left);
if(k == left+1)
return root.data;
else if (left < k)
return min(root.right, k-left-1);
else
return min(root.left, k);
}
this would work too. just call the function with maxNode in the tree
def k_largest(self, node , k):
if k < 0 :
return None
if k == 0:
return node
else:
k -=1
return self.k_largest(self.predecessor(node), k)
I think this is better than the accepted answer because it doesn't need to modify the original tree node to store the number of it's children nodes.
We just need to use the in-order traversal to count the smallest node from the left to right, stop searching once the count equals to K.
private static int count = 0;
public static void printKthSmallestNode(Node node, int k){
if(node == null){
return;
}
if( node.getLeftNode() != null ){
printKthSmallestNode(node.getLeftNode(), k);
}
count ++ ;
if(count <= k )
System.out.println(node.getValue() + ", count=" + count + ", k=" + k);
if(count < k && node.getRightNode() != null)
printKthSmallestNode(node.getRightNode(), k);
}
Best approach is already there.But I'd like to add a simple Code for that
int kthsmallest(treenode *q,int k){
int n = size(q->left) + 1;
if(n==k){
return q->val;
}
if(n > k){
return kthsmallest(q->left,k);
}
if(n < k){
return kthsmallest(q->right,k - n);
}
}
int size(treenode *q){
if(q==NULL){
return 0;
}
else{
return ( size(q->left) + size(q->right) + 1 );
}}
Using auxiliary Result class to track if node is found and current k.
public class KthSmallestElementWithAux {
public int kthsmallest(TreeNode a, int k) {
TreeNode ans = kthsmallestRec(a, k).node;
if (ans != null) {
return ans.val;
} else {
return -1;
}
}
private Result kthsmallestRec(TreeNode a, int k) {
//Leaf node, do nothing and return
if (a == null) {
return new Result(k, null);
}
//Search left first
Result leftSearch = kthsmallestRec(a.left, k);
//We are done, no need to check right.
if (leftSearch.node != null) {
return leftSearch;
}
//Consider number of nodes found to the left
k = leftSearch.k;
//Check if current root is the solution before going right
k--;
if (k == 0) {
return new Result(k - 1, a);
}
//Check right
Result rightBalanced = kthsmallestRec(a.right, k);
//Consider all nodes found to the right
k = rightBalanced.k;
if (rightBalanced.node != null) {
return rightBalanced;
}
//No node found, recursion will continue at the higher level
return new Result(k, null);
}
private class Result {
private final int k;
private final TreeNode node;
Result(int max, TreeNode node) {
this.k = max;
this.node = node;
}
}
}
Python Solution
Time Complexity : O(n)
Space Complexity : O(1)
Idea is to use Morris Inorder Traversal
class Solution(object):
def inorderTraversal(self, current , k ):
while(current is not None): #This Means we have reached Right Most Node i.e end of LDR traversal
if(current.left is not None): #If Left Exists traverse Left First
pre = current.left #Goal is to find the node which will be just before the current node i.e predecessor of current node, let's say current is D in LDR goal is to find L here
while(pre.right is not None and pre.right != current ): #Find predecesor here
pre = pre.right
if(pre.right is None): #In this case predecessor is found , now link this predecessor to current so that there is a path and current is not lost
pre.right = current
current = current.left
else: #This means we have traverse all nodes left to current so in LDR traversal of L is done
k -= 1
if(k == 0):
return current.val
pre.right = None #Remove the link tree restored to original here
current = current.right
else: #In LDR LD traversal is done move to R
k -= 1
if(k == 0):
return current.val
current = current.right
return 0
def kthSmallest(self, root, k):
return self.inorderTraversal( root , k )
public int kthSmallest(TreeNode root, int k) {
LinkedList<TreeNode> stack = new LinkedList<TreeNode>();
while (true) {
while (root != null) {
stack.push(root);
root = root.left;
}
root = stack.pop();
k = k - 1;
if (k == 0) return root.val;
root = root.right;
}
}
Here are the steps:
1.Add a field to each node indicating the size of the tree it roots. This supports operation in O(logN) average time.
2.To save space, one field indicating the size of a node it roots is enough. We don't need to save both the left subtree and right subtree size.
3.Do an inorder traversal until LeftTree == K, LeftTree = Size(T->Left) + 1.
4.Here is the sample code:
int Size(SearchTree T)
{
if(T == NULL) return 0;
return T->Size;
}
Position KthSmallest(SearchTree T, int K)
{
if(T == NULL) return NULL;
int LeftTree;
LeftTree = Size(T->Left) + 1;
if(LeftTree == K) return T;
if(LeftTree > K){
T = KthSmallest(T->Left, K);
}else if(LeftTree < K){
T = KthSmallest(T->Right, K - LeftTree);
}
return T;
}
5.Similarly, we can also get the KthLargest function.
i wrote a neat function to calculate the kth smallest element. I uses in-order traversal and stops when the it reaches the kth smallest element.
void btree::kthSmallest(node* temp, int& k){
if( temp!= NULL) {
kthSmallest(temp->left,k);
if(k >0)
{
if(k==1)
{
cout<<temp->value<<endl;
return;
}
k--;
}
kthSmallest(temp->right,k); }}
public static Node kth(Node n, int k){
Stack<Node> s=new Stack<Node>();
int countPopped=0;
while(!s.isEmpty()||n!=null){
if(n!=null){
s.push(n);
n=n.left;
}else{
node=s.pop();
countPopped++;
if(countPopped==k){
return node;
}
node=node.right;
}
}
}
Related
Remove all nodes in a binary three which don’t lie in any path with sum>= k
Not able to understand answer given HERE Can someone please help to understand. My Algo: Recursively find sum of each path. If sum >=k, put all the nodes in the path in a hashset At the end traverse the tree, remove nodes which are not there in hashset. I am pretty sure, there is a lot of scope of improvement here.
You have tree and you are recursively parsing it like this : go_node(Node node){ go_node(node.left); go_node(node.right); } At your example, you want to delete any subtree which value is less than a given number. The solution is easy, we change our simple function a little and problem will be solved. I let "K" be the global variable to have this code as simple as possible. However you can parse it in go_node method too. int go_node(Node node, int value){ this.total_value = value; total_value += go_node(node.left, value); if (node.left.total_value < K){ node.left = null; } total_value += go_node(node.right, value); if (node.right.total_value < K){ node.right = null; } return total_value; } Why I now I can delete them? When some value returns from a left or right subtree, that subtree is "finished", it is processed and what is important - it gives me adding of all that subtree. So when the total_value of this node is less than K, it means THIS node and ALL childs of this node (and childs of childs etc.) is less than K. Cause when the subtree child returns me a value, that child has in total_value stored the value of all the subtree.
Approch is to traverse the tree and delete nodes in bottom up manner. While traversing the tree, recursively calculate the sum of nodes from root to leaf node of each path. For each visited node, checks the total calculated sum against given sum “k”. If sum is less than k, then free(delete) that node (leaf node) and return the sum back to the previous node. public int removeNodesUtil(Node node, int sum, int k) { if (node == null) return sum; sum =sum + node.data; if (node.left == null && node.right == null) { if (sum < k) { node = null; } return sum; } int leftSum = 0, rightSum = 0, maxSum = 0; if (node.left != null) { leftSum = removeNodesUtil(node.left, sum, k); if (leftSum < k) { node.left = null; } } if (node.right != null) { rightSum = removeNodesUtil(node.right, sum, k); if (rightSum < k) { node.right = null; } } maxSum = Math.max(leftSum, rightSum); if (maxSum < k) { node = null; } return maxSum; }
Given a Binary Tree, find the largest subtree which is a Binary Search Tree
I was asked this question in an interview. I started my answer with the naive approach of finding all the subtree and checking if any of them is a bst. In the process, we will record the size of max bst seen so far. Is there a better approach than this?
What if you do this: Reverse the weight of your graph Use Kruskal algorithm in this way. a. Select the lowest wheighted edge from your set of edges. b. Create a tree only if adding that edge doesn't break your bst constraint. c. Remove that edge from your edges set. You might end up with several trees (Since discarding edges when bst constraint is not satisfied could make you disconnect your original graph), so just select the one with more nodes.
I think of your solution like this: for each subtree of the tree: if the subtree is a binary search tree: compute its size if it is the largest one found so far: best = subtree return best This is inefficient because it does O(n) work for each subtree, and there are up to n subtrees. You can do better by walking the whole tree only once. // Walk the subtree at node. Find the largest subtree that is a binary search tree // and return that tree in *result. Also return that subtree's size and the range // of values it covers in *size, *min, and *max. void walk(Node *node, Node **result, size_t *size, Value *min, Value *max) { Node *result0 = NULL; size_t size0 = 0; Value min0, max0; if (node->left) walk(node->left, &result0, &size0, &min0, &max0); Node *result1 = NULL; size_t size1 = 0; Value min1, max1; if (node->right) walk(node->right, &result1, &size1, &min1, &max1); // If both subtrees are search trees and node->value falls between them, // then node is a search tree. if (result0 == node->left && result1 == node->right && (node->left == NULL || max0 <= node->value) && (node->right == NULL || node->value <= min1)) { *result = node; *size = size0 + 1 + size1; *min = node->left == NULL ? node->value : min0; *max = node->right == NULL ? node->value : max1; } else if (size0 >= size1) { *result = result0; *size = size0; *min = min0; *max = max0; } else { *result = result1; *size = size1; *min = min1; *max = max1; } } Node * findLargestBinarySearchSubtree(Node *root) { Node *result; size_t size; Value min, max; walk(root, &result, &size, &min, &max); return result; }
This website seems to cover this problem under: Binary Search Tree Checking. Specifically, here's the excerpt to the solution in C++ /* Returns true if the given tree is a binary search tree (efficient version). */ int isBST2(struct node* node) { return(isBSTUtil(node, INT_MIN, INT_MAX)); } /* Returns true if the given tree is a BST and its values are >= min and <= max. */ int isBSTUtil(struct node* node, int min, int max) { if (node==NULL) return(true); // false if this node violates the min/max constraint if (node->data<min || node->data>max) return(false); // otherwise check the subtrees recursively, // tightening the min or max constraint return isBSTUtil(node->left, min, node->data) && isBSTUtil(node->right, node->data+1, max) ); }
I assume there is O(n) complexity to solve. bool is_bst(node * cur) { if (cur == NULL) return true; // if calculated before cur vertex. if (hash_set_bst[cur] != -1) return hash_set_bst[cur]; int left_value = MIN; int right_value = MAX; if (cur -> left != NULL) left_value = cur -> left -> value; if (cur -> right != NULL) right_value = cur -> right -> value; if (cur -> value > left_value && cur -> value < right_value) { hash_set_bst[cur] = is_bst(cur->left) && is_bst(cur->right); return hash_set_bst[cur]; } else { hash_set_bst[cur] = 0; is_bst(cur->left); is_bst(cur->right); return hash_set_bst[cur]; } } Now for each node you know if it can start BST or not. Now you need to calculate sub tree sizes and then iterate throgh all nodes and figure out what's the max size having flag if node can start BST. To calculate sizes you may do the following: int dfs(node * cur) { if (cur == NULL) return 0; size[cur] = 1 + dfs(cur->left) + dfs(cur->right); return size[cur]; }
do an in order traversal of the binary tree, if any subtree is BST, in order traversal will produce an ascending sequence, record the size of the tree as you go. when u hit a break point, recursive in order traversal that tree using the break point as root, record its size. pick the biggest one.
find kth smallest in bst using recursive inorder
I am trying to find the kth smallest in BST. public void findKthSmallest(BSTNode<T> node, int k) { if(node == null) return; findKthSmallest(node.left, k); count++; if (k == count) { System.out.println("Kth smallest: " + node.data); return; } findKthSmallest(node.right, k); } here count is a instance variable. I am not able to figure out how to implement it using count as a parameter(local varaible) in the function, since it get resets when function returns. Any idea??
Since this is Java and you have no pass by reference, I think the easiest is to modify findKthSmallest to return how many nodes are in the subtree rooted at node. Something like this: public int findKthSmallest(BSTNode<T> node, int k) { if(node == null) return 0; int left = findKthSmallest(node.left, k); if (k == left + 1) { System.out.println("Kth smallest: " + node.data); return 1; } return 1 + left + findKthSmallest(node.right, k); }
I would like to make a small correction in IVlad's approach. When we are searching left, the problem is to find kth smallest. However, when searching right we need to find k-left-1 (discarding the left subtree+current node). In java we cant return multiple values other than creating a class. So made a hack for that by passing an array as parameter. Here is the code: public int kthSmallest(TreeNode node, int k, TreeNode kthNode[]) { int leftCount = 0; int rightCount = 0; if(node.left!=null) { leftCount = kthSmallest(node.left, k, kthNode); } if(leftCount==k-1) { kthNode[0] = node; // We can also return from here } if(node.right!=null) { rightCount = kthSmallest(node.right, k-leftCount-1, kthNode); } return leftCount + 1 + rightCount; } public TreeNode kthSmallest(TreeNode node, int k) { TreeNode kNode[] = new TreeNode[1]; int nodeCount = kthSmallest(node, k, kNode); return kNode[0]; }
Nth largest element in a binary search tree
How to find the Nth largest node in a BST? Do I keep a count variable while doing In Order Traversal of a BST? Return the element when the count = N???
The idea is very simple: traverse the tree in decreasing order of the values of each node. When you reach the Nth node, print that node value. Here is the recursive code. void printNthNode(Node* root, int N) { if(root == NULL) return; static int index = 0; //These will initialize to zero only once as its static //For every Node go to the right of that node first. printNthNode(root->right, N); //Right has returned and now current node will be greatest if(++index == N) { printf("%d\n", root->data); return; } //And at last go to the left printNthNode(root->left, N); } Edit - As per the comments below, looks like this is one-time call function due to the static local variable. This can be solved by passing wrapper object for index as follows: class WrapIndex { public: int index; }; and method signature would change to void printNthNode(Node* root, int N, WrapIndex wrapInd) Now, we don't need a local static variable; instead use index of the wrapper object. The call would look like WrapIndex wrapInd = new WrapIndex(); wrapInd.index=0; printNthNode(root,7,wrapInd); wrapInd.index=0; printNthNode(root,2,wrapInd);
Hint: use inorder traversal of the tree. It can print out the items in sorted order, so you can sure find the Nth largest item. Keep a counter as you "walk", incrementing each time you "visit" a node. Edit: while IVlad's answer is indeed faster, it requires you to keep extra information in the nodes. This answer doesn't but it's O(n). Just pointing out that this is a tradeoff you have to be aware of.
See my answer here. You can do this in O(log n) on average where n = number of nodes. Worst case is still O(n) IF the tree isn't balanced (always O(log n) if it is balanced however). In order traversal is always O(n) however.
Use a inverted inorder tranversal.that is go to right child first instead of left child. recursively this can be obtained as follows: The most important issue that a global count must be used when considering recursive solution. reverseInorder(root){ if(root!=null){ reverseInorder(root->rightChild); self reverseInorder(root->leftChild); } } Solution in java package datastructure.binaryTree; import datastructure.nodes.BinaryTreeNode; public class NthElementFromEnd { private BinaryTree tree=null; int currCount=0; public NthElementFromEnd(int[] dataArray) { this.tree=new BinaryTree(dataArray); } private void getElementFromEnd(int n){ getElementFromEnd(this.tree.getRoot(),n); } private void getElementFromEnd(BinaryTreeNode node,int n){ if(node!=null){ if(currCount<n) getElementFromEnd(node.getRightChild(),n); currCount++; if(currCount==n) { System.out.print(" "+node.getData()); return; } if(currCount<n) getElementFromEnd(node.getLeftChild(),n); } } public static void main(String args[]){ int data[]={1,2,3,4,5,6,7,8,9}; int n=2; new NthElementFromEnd(data).getElementFromEnd(n); } }
int nLargeBST(node *root, int N) { if (!root || N < 0) { return -1; } nLargeBST(root->left, N); --N; if(N == 0) { return root->val; } nLargeBST(root->right, N); }
This piece of code is from my assignment and one of the condition was not to use arrays. In order to make the code more compact and readable you can use stringName.split("|"). Since the method is recursive I use the stringBuilder which has the following structure: "counter|orderOfElementToFind|dataInrequiredNode" protected StringBuilder t(StringBuilder s) { if (lc != null) { lc.t(s); } if((s.toString().charAt(s.toString().length() - 1)) == '|') { String str = s.toString(); s.delete(0, s.length()); int counter = 0, k = 0; String strTemp = "", newStrBuilContent = ""; for (int i = 0, c = 0 ; i < str.length(); ++i) { if (c == 0) { if (str.charAt(i) != '|') { strTemp += str.charAt(i); } else { counter = Integer.parseInt(strTemp); ++c; strTemp = ""; } } else { if (str.charAt(i) != '|') { strTemp += str.charAt(i); } else { k = Integer.parseInt(strTemp); } } counter ++; newStrBuilContent = (counter + "|" + k + "|"); s.append(newStrBuilContent); if (counter == k) { double ldata = this.getData(); s.append(ldata); } } if (rc != null) { rc.t(s); } return s; } and the method call: // the value of counter ad the beginning is 0 and data // segment is missing String s = ("0|" + order +"|"); StringBuilder strBldr = new StringBuilder(s); String content = sTree.t(strBldr).toString(); s = ""; for (int i = 0, c = 0; i < content.length(); ++i) { if (c < 2) { if (content.charAt(i) == '|') { ++c; } } else { s += content.charAt(i); } } `
Maintain size of subtree at eachnode(root.size some thing like that). for example {2,3,1} is a binary tree with root 2 then the size of node (2) is 3, node (1) size is 1, and node (2) size is 1 if u want to find 4 th larget element in the tree with root node size 23 , think about its rank the max element rank is 23, because the root node size is 23. so 4 th largest element rank is 23-4+1= 20 so we have to find 20th rank element in the given tree initially declare a rank=0 flag to zero starting from root node find its rank (rank+ size of left child + 1) for example left child size is 16 then root element rank is 17(rank+size of left child +1) so we have to look for the element with the rank 20. so obviously we have to traverse to its right child traverse to right child and based on above formula find right child rank(based on above formula, note: now rank flag value is is 17),decide whether to go right or left based on the rank repeat this process recursevely untill we found rank==20
I would do it by going though the tree from biggest to smallest element and returning value when asked position is reached. I implemented similar task for second largest value. Value of 2 is hardcoded, but is it easy to change with additional parameter :) void BTree::findSecondLargestValueUtil(Node* r, int &c, int &v) { if(r->right) { this->findSecondLargestValueUtil(r->right, c, v); } c++; if(c==2) { v = r->value; return; } if(r->left) { this->findSecondLargestValueUtil(r->left, c, v); } } int BTree::findSecondLargestValue() { int c = 0; int v = -1; this->findSecondLargestValueUtil(this->root, c, v); return v; }
// C++ program to find k'th largest element in BST #include<iostream> using namespace std; struct Node { int key; Node *left, *right; }; // A utility function to create a new BST node Node *newNode(int item) { Node *temp = new Node; temp->key = item; temp->left = temp->right = NULL; return temp; } // A function to find k'th largest element in a given tree. void kthLargestUtil(Node *root, int k, int &c) { // Base cases, the second condition is important to // avoid unnecessary recursive calls if (root == NULL || c >= k) return; // Follow reverse inorder traversal so that the // largest element is visited first kthLargestUtil(root->right, k, c); // Increment count of visited nodes c++; // If c becomes k now, then this is the k'th largest if (c == k) { cout << "K'th largest element is " << root->key << endl; return; } // Recur for left subtree kthLargestUtil(root->left, k, c); } // Function to find k'th largest element void kthLargest(Node *root, int k) { // Initialize count of nodes visited as 0 int c = 0; // Note that c is passed by reference kthLargestUtil(root, k, c); } /* A utility function to insert a new node with given key in BST */ Node* insert(Node* node, int key) { /* If the tree is empty, return a new node */ if (node == NULL) return newNode(key); /* Otherwise, recur down the tree */ if (key < node->key) node->left = insert(node->left, key); else if (key > node->key) node->right = insert(node->right, key); /* return the (unchanged) node pointer */ return node; } // Driver Program to test above functions int main() { /* Let us create following BST 50 / \ 30 70 / \ / \ 20 40 60 80 */ Node *root = NULL; root = insert(root, 50); insert(root, 30); insert(root, 20); insert(root, 40); insert(root, 70); insert(root, 60); insert(root, 80); int c = 0; for (int k=1; k<=7; k++) kthLargest(root, k); return 0; }
Swift version. This follows closely with what Vallabh Patade said. The counter is increased by 1 when it tries to go through a node that has no child though. A bit different than his. class BinaryNode { var val: Int var left: BinaryNode? var right: BinaryNode? init(value: Int) { self.val = value } } func findMaxValue(_ n: Int, from root: BinaryNode?) { var counter = 0 maxValue(counter: &counter, n: n, node: root) } private func maxValue(counter: inout Int, n: Int, node: BinaryNode?) { if node == nil { counter += 1 return } maxValue(counter: &counter, n: n, node: node?.right) // If the counter has reached the nth node we're looking for. if counter == n { if let val = node?.val { print(val) } } maxValue(counter: &counter, n: n, node: node?.left) }
Here is how you can do this by a slight modification of the in-order traversal of the binary search tree - we are finding the kth largest element; void kthLargest(Node node, int k, int count) { if(node != null) { nthLargest(node.left,k,count); //traversing the left node //while visit the node we do the following count++; // increment the count and check if that is equal to k if ( count == k ) { System.out.println("Node found "+node.value); } nthLargest(node.right,k,count); //traversing the right node } } But the problem in this way you are going to reach the kth smallest element and hence you method call should be this: as kth largest element = (n-k)th smallest element. nthLargest(root,n-k,0);
K’th Largest Element in BST . Learn how to think for such problem and solve with recursion . Kth Larget Explanation Recursion
How to find the lowest common ancestor of two nodes in any binary tree?
The Binary Tree here is may not necessarily be a Binary Search Tree. The structure could be taken as - struct node { int data; struct node *left; struct node *right; }; The maximum solution I could work out with a friend was something of this sort - Consider this binary tree : The inorder traversal yields - 8, 4, 9, 2, 5, 1, 6, 3, 7 And the postorder traversal yields - 8, 9, 4, 5, 2, 6, 7, 3, 1 So for instance, if we want to find the common ancestor of nodes 8 and 5, then we make a list of all the nodes which are between 8 and 5 in the inorder tree traversal, which in this case happens to be [4, 9, 2]. Then we check which node in this list appears last in the postorder traversal, which is 2. Hence the common ancestor for 8 and 5 is 2. The complexity for this algorithm, I believe is O(n) (O(n) for inorder/postorder traversals, the rest of the steps again being O(n) since they are nothing more than simple iterations in arrays). But there is a strong chance that this is wrong. :-) But this is a very crude approach, and I'm not sure if it breaks down for some case. Is there any other (possibly more optimal) solution to this problem?
Starting from root node and moving downwards if you find any node that has either p or q as its direct child then it is the LCA. (edit - this should be if p or q is the node's value, return it. Otherwise it will fail when one of p or q is a direct child of the other.) Else if you find a node with p in its right(or left) subtree and q in its left(or right) subtree then it is the LCA. The fixed code looks like: treeNodePtr findLCA(treeNodePtr root, treeNodePtr p, treeNodePtr q) { // no root no LCA. if(!root) { return NULL; } // if either p or q is the root then root is LCA. if(root==p || root==q) { return root; } else { // get LCA of p and q in left subtree. treeNodePtr l=findLCA(root->left , p , q); // get LCA of p and q in right subtree. treeNodePtr r=findLCA(root->right , p, q); // if one of p or q is in leftsubtree and other is in right // then root it the LCA. if(l && r) { return root; } // else if l is not null, l is LCA. else if(l) { return l; } else { return r; } } } The below code fails when either is the direct child of other. treeNodePtr findLCA(treeNodePtr root, treeNodePtr p, treeNodePtr q) { // no root no LCA. if(!root) { return NULL; } // if either p or q is direct child of root then root is LCA. if(root->left==p || root->left==q || root->right ==p || root->right ==q) { return root; } else { // get LCA of p and q in left subtree. treeNodePtr l=findLCA(root->left , p , q); // get LCA of p and q in right subtree. treeNodePtr r=findLCA(root->right , p, q); // if one of p or q is in leftsubtree and other is in right // then root it the LCA. if(l && r) { return root; } // else if l is not null, l is LCA. else if(l) { return l; } else { return r; } } } Code In Action
Nick Johnson is correct that a an O(n) time complexity algorithm is the best you can do if you have no parent pointers.) For a simple recursive version of that algorithm see the code in Kinding's post which runs in O(n) time. But keep in mind that if your nodes have parent pointers, an improved algorithm is possible. For both nodes in question construct a list containing the path from root to the node by starting at the node, and front inserting the parent. So for 8 in your example, you get (showing steps): {4}, {2, 4}, {1, 2, 4} Do the same for your other node in question, resulting in (steps not shown): {1, 2} Now compare the two lists you made looking for the first element where the list differ, or the last element of one of the lists, whichever comes first. This algorithm requires O(h) time where h is the height of the tree. In the worst case O(h) is equivalent to O(n), but if the tree is balanced, that is only O(log(n)). It also requires O(h) space. An improved version is possible that uses only constant space, with code shown in CEGRD's post Regardless of how the tree is constructed, if this will be an operation you perform many times on the tree without changing it in between, there are other algorithms you can use that require O(n) [linear] time preparation, but then finding any pair takes only O(1) [constant] time. For references to these algorithms, see the the lowest common ancestor problem page on Wikipedia. (Credit to Jason for originally posting this link)
Here is the working code in JAVA public static Node LCA(Node root, Node a, Node b) { if (root == null) { return null; } // If the root is one of a or b, then it is the LCA if (root == a || root == b) { return root; } Node left = LCA(root.left, a, b); Node right = LCA(root.right, a, b); // If both nodes lie in left or right then their LCA is in left or right, // Otherwise root is their LCA if (left != null && right != null) { return root; } return (left != null) ? left : right; }
The answers given so far uses recursion or stores, for instance, a path in memory. Both of these approaches might fail if you have a very deep tree. Here is my take on this question. When we check the depth (distance from the root) of both nodes, if they are equal, then we can safely move upward from both nodes towards the common ancestor. If one of the depth is bigger then we should move upward from the deeper node while staying in the other one. Here is the code: findLowestCommonAncestor(v,w): depth_vv = depth(v); depth_ww = depth(w); vv = v; ww = w; while( depth_vv != depth_ww ) { if ( depth_vv > depth_ww ) { vv = parent(vv); depth_vv--; else { ww = parent(ww); depth_ww--; } } while( vv != ww ) { vv = parent(vv); ww = parent(ww); } return vv; The time complexity of this algorithm is: O(n). The space complexity of this algorithm is: O(1). Regarding the computation of the depth, we can first remember the definition: If v is root, depth(v) = 0; Otherwise, depth(v) = depth(parent(v)) + 1. We can compute depth as follows: depth(v): int d = 0; vv = v; while ( vv is not root ) { vv = parent(vv); d++; } return d;
Well, this kind of depends how your Binary Tree is structured. Presumably you have some way of finding the desired leaf node given the root of the tree - simply apply that to both values until the branches you choose diverge. If you don't have a way to find the desired leaf given the root, then your only solution - both in normal operation and to find the last common node - is a brute-force search of the tree.
This can be found at:- http://goursaha.freeoda.com/DataStructure/LowestCommonAncestor.html tree_node_type *LowestCommonAncestor( tree_node_type *root , tree_node_type *p , tree_node_type *q) { tree_node_type *l , *r , *temp; if(root==NULL) { return NULL; } if(root->left==p || root->left==q || root->right ==p || root->right ==q) { return root; } else { l=LowestCommonAncestor(root->left , p , q); r=LowestCommonAncestor(root->right , p, q); if(l!=NULL && r!=NULL) { return root; } else { temp = (l!=NULL)?l:r; return temp; } } }
Tarjan's off-line least common ancestors algorithm is good enough (cf. also Wikipedia). There is more on the problem (the lowest common ancestor problem) on Wikipedia.
To find out common ancestor of two node :- Find the given node Node1 in the tree using binary search and save all nodes visited in this process in an array say A1. Time - O(logn), Space - O(logn) Find the given Node2 in the tree using binary search and save all nodes visited in this process in an array say A2. Time - O(logn), Space - O(logn) If A1 list or A2 list is empty then one the node does not exist so there is no common ancestor. If A1 list and A2 list are non-empty then look into the list until you find non-matching node. As soon as you find such a node then node prior to that is common ancestor. This would work for binary search tree.
I have made an attempt with illustrative pictures and working code in Java, http://tech.bragboy.com/2010/02/least-common-ancestor-without-using.html
The below recursive algorithm will run in O(log N) for a balanced binary tree. If either of the nodes passed into the getLCA() function are the same as the root then the root will be the LCA and there will be no need to perform any recussrion. Test cases. [1] Both nodes n1 & n2 are in the tree and reside on either side of their parent node. [2] Either node n1 or n2 is the root, the LCA is the root. [3] Only n1 or n2 is in the tree, LCA will be either the root node of the left subtree of the tree root, or the LCA will be the root node of the right subtree of the tree root. [4] Neither n1 or n2 is in the tree, there is no LCA. [5] Both n1 and n2 are in a straight line next to each other, LCA will be either of n1 or n2 which ever is closes to the root of the tree. //find the search node below root bool findNode(node* root, node* search) { //base case if(root == NULL) return false; if(root->val == search->val) return true; //search for the node in the left and right subtrees, if found in either return true return (findNode(root->left, search) || findNode(root->right, search)); } //returns the LCA, n1 & n2 are the 2 nodes for which we are //establishing the LCA for node* getLCA(node* root, node* n1, node* n2) { //base case if(root == NULL) return NULL; //If 1 of the nodes is the root then the root is the LCA //no need to recurse. if(n1 == root || n2 == root) return root; //check on which side of the root n1 and n2 reside bool n1OnLeft = findNode(root->left, n1); bool n2OnLeft = findNode(root->left, n2); //n1 & n2 are on different sides of the root, so root is the LCA if(n1OnLeft != n2OnLeft) return root; //if both n1 & n2 are on the left of the root traverse left sub tree only //to find the node where n1 & n2 diverge otherwise traverse right subtree if(n1OnLeft) return getLCA(root->left, n1, n2); else return getLCA(root->right, n1, n2); }
Just walk down from the whole tree's root as long as both given nodes ,say p and q, for which Ancestor has to be found, are in the same sub-tree (meaning their values are both smaller or both larger than root's). This walks straight from the root to the Least Common Ancestor , not looking at the rest of the tree, so it's pretty much as fast as it gets. A few ways to do it. Iterative, O(1) space Python def lowestCommonAncestor(self, root, p, q): while (root.val - p.val) * (root.val - q.val) > 0: root = (root.left, root.right)[p.val > root.val] return root Java public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { while ((root.val - p.val) * (root.val - q.val) > 0) root = p.val < root.val ? root.left : root.right; return root; } in case of overflow, I'd do (root.val - (long)p.val) * (root.val - (long)q.val) Recursive Python def lowestCommonAncestor(self, root, p, q): next = p.val < root.val > q.val and root.left or \ p.val > root.val < q.val and root.right return self.lowestCommonAncestor(next, p, q) if next else root Java public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { return (root.val - p.val) * (root.val - q.val) < 1 ? root : lowestCommonAncestor(p.val < root.val ? root.left : root.right, p, q); }
Node *LCA(Node *root, Node *p, Node *q) { if (!root) return NULL; if (root == p || root == q) return root; Node *L = LCA(root->left, p, q); Node *R = LCA(root->right, p, q); if (L && R) return root; // if p and q are on both sides return L ? L : R; // either one of p,q is on one side OR p,q is not in L&R subtrees }
Consider this tree If we do postorder and preorder traversal and find the first occuring common predecessor and successor, we get the common ancestor. postorder => 0,2,1,5,4,6,3,8,10,11,9,14,15,13,12,7 preorder => 7,3,1,0,2,6,4,5,12,9,8,11,10,13,15,14 eg :1 Least common ancestor of 8,11 in postorder we have = >9,14,15,13,12,7 after 8 & 11 in preorder we have =>7,3,1,0,2,6,4,5,12,9 before 8 & 11 9 is the first common number that occurs after 8& 11 in postorder and before 8 & 11 in preorder, hence 9 is the answer eg :2 Least common ancestor of 5,10 11,9,14,15,13,12,7 in postorder 7,3,1,0,2,6,4 in preorder 7 is the first number that occurs after 5,10 in postorder and before 5,10 in preorder, hence 7 is the answer
If it is full binary tree with children of node x as 2*x and 2*x+1 than there is a faster way to do it int get_bits(unsigned int x) { int high = 31; int low = 0,mid; while(high>=low) { mid = (high+low)/2; if(1<<mid==x) return mid+1; if(1<<mid<x) { low = mid+1; } else { high = mid-1; } } if(1<<mid>x) return mid; return mid+1; } unsigned int Common_Ancestor(unsigned int x,unsigned int y) { int xbits = get_bits(x); int ybits = get_bits(y); int diff,kbits; unsigned int k; if(xbits>ybits) { diff = xbits-ybits; x = x >> diff; } else if(xbits<ybits) { diff = ybits-xbits; y = y >> diff; } k = x^y; kbits = get_bits(k); return y>>kbits; } How does it work get bits needed to represent x & y which using binary search is O(log(32)) the common prefix of binary notation of x & y is the common ancestor whichever is represented by larger no of bits is brought to same bit by k >> diff k = x^y erazes common prefix of x & y find bits representing the remaining suffix shift x or y by suffix bits to get common prefix which is the common ancestor. This works because basically divide the larger number by two recursively until both numbers are equal. That number is the common ancestor. Dividing is effectively the right shift opearation. So we need to find common prefix of two numbers to find the nearest ancestor
In scala, you can: abstract class Tree case class Node(a:Int, left:Tree, right:Tree) extends Tree case class Leaf(a:Int) extends Tree def lca(tree:Tree, a:Int, b:Int):Tree = { tree match { case Node(ab,l,r) => { if(ab==a || ab ==b) tree else { val temp = lca(l,a,b); val temp2 = lca(r,a,b); if(temp!=null && temp2 !=null) tree else if (temp==null && temp2==null) null else if (temp==null) r else l } } case Leaf(ab) => if(ab==a || ab ==b) tree else null } }
The lowest common ancestor between two nodes node1 and node2 is the lowest node in a tree that has both nodes as descendants. The binary tree is traversed from the root node, until both nodes are found. Every time a node is visited, it is added to a dictionary (called parent). Once both nodes are found in the binary tree, the ancestors of node1 are obtained using the dictionary and added to a set (called ancestors). This step is followed in the same manner for node2. If the ancestor of node2 is present in the ancestors set for node1, it is the first common ancestor between them. Below is the iterative python solution implemented using stack and dictionary with the following points: A node can be a descendant of itself All nodes in the binary tree are unique node1 and node2 will exist in the binary tree class Node: def __init__(self, data=None, left=None, right=None): self.data = data self.left = left self.right = right def lowest_common_ancestor(root, node1, node2): parent = {root: None} stack = [root] while node1 not in parent or node2 not in parent: node = stack[-1] stack.pop() if node.left: parent[node.left] = node stack.append(node.left) if node.right: parent[node.right] = node stack.append(node.right) ancestors = set() while node1: ancestors.add(node1) node1 = parent[node1] while node2 not in ancestors: node2 = parent[node2] return node2.data def main(): ''' Construct the below binary tree: 30 / \ / \ / \ 11 29 / \ / \ 8 12 25 14 ''' root = Node(30) root.left = Node(11) root.right = Node(29) root.left.left = Node(8) root.left.right = Node(12) root.right.left = Node(25) root.right.right = Node(14) print(lowest_common_ancestor(root, root.left.left, root.left.right)) # 11 print(lowest_common_ancestor(root, root.left.left, root.left)) # 11 print(lowest_common_ancestor(root, root.left.left, root.right.right)) # 30 if __name__ == '__main__': main() The complexity of this approach is: O(n)
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { if(root==null || root == p || root == q){ return root; } TreeNode left = lowestCommonAncestor(root.left,p,q); TreeNode right = lowestCommonAncestor(root.right,p,q); return left == null ? right : right == null ? left : root; }
Here is the C++ way of doing it. Have tried to keep the algorithm as much easy as possible to understand: // Assuming that `BinaryNode_t` has `getData()`, `getLeft()` and `getRight()` class LowestCommonAncestor { typedef char type; // Data members which would behave as place holders const BinaryNode_t* m_pLCA; type m_Node1, m_Node2; static const unsigned int TOTAL_NODES = 2; // The core function which actually finds the LCA; It returns the number of nodes found // At any point of time if the number of nodes found are 2, then it updates the `m_pLCA` and once updated, we have found it! unsigned int Search (const BinaryNode_t* const pNode) { if(pNode == 0) return 0; unsigned int found = 0; found += (pNode->getData() == m_Node1); found += (pNode->getData() == m_Node2); found += Search(pNode->getLeft()); // below condition can be after this as well found += Search(pNode->getRight()); if(found == TOTAL_NODES && m_pLCA == 0) m_pLCA = pNode; // found ! return found; } public: // Interface method which will be called externally by the client const BinaryNode_t* Search (const BinaryNode_t* const pHead, const type node1, const type node2) { // Initialize the data members of the class m_Node1 = node1; m_Node2 = node2; m_pLCA = 0; // Find the LCA, populate to `m_pLCANode` and return (void) Search(pHead); return m_pLCA; } }; How to use it: LowestCommonAncestor lca; BinaryNode_t* pNode = lca.Search(pWhateverBinaryTreeNodeToBeginWith); if(pNode != 0) ...
The easiest way to find the Lowest Common Ancestor is using the following algorithm: Examine root node if value1 and value2 are strictly less that the value at the root node Examine left subtree else if value1 and value2 are strictly greater that the value at the root node Examine right subtree else return root public int LCA(TreeNode root, int value 1, int value 2) { while (root != null) { if (value1 < root.data && value2 < root.data) return LCA(root.left, value1, value2); else if (value2 > root.data && value2 2 root.data) return LCA(root.right, value1, value2); else return root } return null; }
I found a solution Take inorder Take preorder Take postorder Depending on 3 traversals, you can decide who is the LCA. From LCA find distance of both nodes. Add these two distances, which is the answer.
Here is what I think, Find the route for the fist node , store it on to arr1. Start finding the route for the 2 node , while doing so check every value from root to arr1. time when value differs , exit. Old matched value is the LCA. Complexity : step 1 : O(n) , step 2 =~ O(n) , total =~ O(n).
Here are two approaches in c# (.net) (both discussed above) for reference: Recursive version of finding LCA in binary tree (O(N) - as at most each node is visited) (main points of the solution is LCA is (a) only node in binary tree where both elements reside either side of the subtrees (left and right) is LCA. (b) And also it doesn't matter which node is present either side - initially i tried to keep that info, and obviously the recursive function become so confusing. once i realized it, it became very elegant. Searching both nodes (O(N)), and keeping track of paths (uses extra space - so, #1 is probably superior even thought the space is probably negligible if the binary tree is well balanced as then extra memory consumption will be just in O(log(N)). so that the paths are compared (essentailly similar to accepted answer - but the paths is calculated by assuming pointer node is not present in the binary tree node) Just for the completion (not related to question), LCA in BST (O(log(N)) Tests Recursive: private BinaryTreeNode LeastCommonAncestorUsingRecursion(BinaryTreeNode treeNode, int e1, int e2) { Debug.Assert(e1 != e2); if(treeNode == null) { return null; } if((treeNode.Element == e1) || (treeNode.Element == e2)) { //we don't care which element is present (e1 or e2), we just need to check //if one of them is there return treeNode; } var nLeft = this.LeastCommonAncestorUsingRecursion(treeNode.Left, e1, e2); var nRight = this.LeastCommonAncestorUsingRecursion(treeNode.Right, e1, e2); if(nLeft != null && nRight != null) { //note that this condition will be true only at least common ancestor return treeNode; } else if(nLeft != null) { return nLeft; } else if(nRight != null) { return nRight; } return null; } where above private recursive version is invoked by following public method: public BinaryTreeNode LeastCommonAncestorUsingRecursion(int e1, int e2) { var n = this.FindNode(this._root, e1); if(null == n) { throw new Exception("Element not found: " + e1); } if (e1 == e2) { return n; } n = this.FindNode(this._root, e2); if (null == n) { throw new Exception("Element not found: " + e2); } var node = this.LeastCommonAncestorUsingRecursion(this._root, e1, e2); if (null == node) { throw new Exception(string.Format("Least common ancenstor not found for the given elements: {0},{1}", e1, e2)); } return node; } Solution by keeping track of paths of both nodes: public BinaryTreeNode LeastCommonAncestorUsingPaths(int e1, int e2) { var path1 = new List<BinaryTreeNode>(); var node1 = this.FindNodeAndPath(this._root, e1, path1); if(node1 == null) { throw new Exception(string.Format("Element {0} is not found", e1)); } if(e1 == e2) { return node1; } List<BinaryTreeNode> path2 = new List<BinaryTreeNode>(); var node2 = this.FindNodeAndPath(this._root, e2, path2); if (node1 == null) { throw new Exception(string.Format("Element {0} is not found", e2)); } BinaryTreeNode lca = null; Debug.Assert(path1[0] == this._root); Debug.Assert(path2[0] == this._root); int i = 0; while((i < path1.Count) && (i < path2.Count) && (path2[i] == path1[i])) { lca = path1[i]; i++; } Debug.Assert(null != lca); return lca; } where FindNodeAndPath is defined as private BinaryTreeNode FindNodeAndPath(BinaryTreeNode node, int e, List<BinaryTreeNode> path) { if(node == null) { return null; } if(node.Element == e) { path.Add(node); return node; } var n = this.FindNodeAndPath(node.Left, e, path); if(n == null) { n = this.FindNodeAndPath(node.Right, e, path); } if(n != null) { path.Insert(0, node); return n; } return null; } BST (LCA) - not related (just for completion for reference) public BinaryTreeNode BstLeastCommonAncestor(int e1, int e2) { //ensure both elements are there in the bst var n1 = this.BstFind(e1, throwIfNotFound: true); if(e1 == e2) { return n1; } this.BstFind(e2, throwIfNotFound: true); BinaryTreeNode leastCommonAcncestor = this._root; var iterativeNode = this._root; while(iterativeNode != null) { if((iterativeNode.Element > e1 ) && (iterativeNode.Element > e2)) { iterativeNode = iterativeNode.Left; } else if((iterativeNode.Element < e1) && (iterativeNode.Element < e2)) { iterativeNode = iterativeNode.Right; } else { //i.e; either iterative node is equal to e1 or e2 or in between e1 and e2 return iterativeNode; } } //control will never come here return leastCommonAcncestor; } Unit Tests [TestMethod] public void LeastCommonAncestorTests() { int[] a = { 13, 2, 18, 1, 5, 17, 20, 3, 6, 16, 21, 4, 14, 15, 25, 22, 24 }; int[] b = { 13, 13, 13, 2, 13, 18, 13, 5, 13, 18, 13, 13, 14, 18, 25, 22}; BinarySearchTree bst = new BinarySearchTree(); foreach (int e in a) { bst.Add(e); bst.Delete(e); bst.Add(e); } for(int i = 0; i < b.Length; i++) { var n = bst.BstLeastCommonAncestor(a[i], a[i + 1]); Assert.IsTrue(n.Element == b[i]); var n1 = bst.LeastCommonAncestorUsingPaths(a[i], a[i + 1]); Assert.IsTrue(n1.Element == b[i]); Assert.IsTrue(n == n1); var n2 = bst.LeastCommonAncestorUsingRecursion(a[i], a[i + 1]); Assert.IsTrue(n2.Element == b[i]); Assert.IsTrue(n2 == n1); Assert.IsTrue(n2 == n); } }
If someone interested in pseudo code(for university home works) here is one. GETLCA(BINARYTREE BT, NODE A, NODE B) IF Root==NIL return NIL ENDIF IF Root==A OR root==B return Root ENDIF Left = GETLCA (Root.Left, A, B) Right = GETLCA (Root.Right, A, B) IF Left! = NIL AND Right! = NIL return root ELSEIF Left! = NIL Return Left ELSE Return Right ENDIF
Although this has been answered already, this is my approach to this problem using C programming language. Although the code shows a binary search tree (as far as insert() is concerned), but the algorithm works for a binary tree as well. The idea is to go over all nodes that lie from node A to node B in inorder traversal, lookup the indices for these in the post order traversal. The node with maximum index in post order traversal is the lowest common ancestor. This is a working C code to implement a function to find the lowest common ancestor in a binary tree. I am providing all the utility functions etc. as well, but jump to CommonAncestor() for quick understanding. #include <stdio.h> #include <malloc.h> #include <stdlib.h> #include <math.h> static inline int min (int a, int b) { return ((a < b) ? a : b); } static inline int max (int a, int b) { return ((a > b) ? a : b); } typedef struct node_ { int value; struct node_ * left; struct node_ * right; } node; #define MAX 12 int IN_ORDER[MAX] = {0}; int POST_ORDER[MAX] = {0}; createNode(int value) { node * temp_node = (node *)malloc(sizeof(node)); temp_node->left = temp_node->right = NULL; temp_node->value = value; return temp_node; } node * insert(node * root, int value) { if (!root) { return createNode(value); } if (root->value > value) { root->left = insert(root->left, value); } else { root->right = insert(root->right, value); } return root; } /* Builds inorder traversal path in the IN array */ void inorder(node * root, int * IN) { static int i = 0; if (!root) return; inorder(root->left, IN); IN[i] = root->value; i++; inorder(root->right, IN); } /* Builds post traversal path in the POST array */ void postorder (node * root, int * POST) { static int i = 0; if (!root) return; postorder(root->left, POST); postorder(root->right, POST); POST[i] = root->value; i++; } int findIndex(int * A, int value) { int i = 0; for(i = 0; i< MAX; i++) { if(A[i] == value) return i; } } int CommonAncestor(int val1, int val2) { int in_val1, in_val2; int post_val1, post_val2; int j=0, i = 0; int max_index = -1; in_val1 = findIndex(IN_ORDER, val1); in_val2 = findIndex(IN_ORDER, val2); post_val1 = findIndex(POST_ORDER, val1); post_val2 = findIndex(POST_ORDER, val2); for (i = min(in_val1, in_val2); i<= max(in_val1, in_val2); i++) { for(j = 0; j < MAX; j++) { if (IN_ORDER[i] == POST_ORDER[j]) { if (j > max_index) { max_index = j; } } } } printf("\ncommon ancestor of %d and %d is %d\n", val1, val2, POST_ORDER[max_index]); return max_index; } int main() { node * root = NULL; /* Build a tree with following values */ //40, 20, 10, 30, 5, 15, 25, 35, 1, 80, 60, 100 root = insert(root, 40); insert(root, 20); insert(root, 10); insert(root, 30); insert(root, 5); insert(root, 15); insert(root, 25); insert(root, 35); insert(root, 1); insert(root, 80); insert(root, 60); insert(root, 100); /* Get IN_ORDER traversal in the array */ inorder(root, IN_ORDER); /* Get post order traversal in the array */ postorder(root, POST_ORDER); CommonAncestor(1, 100); }
There can be one more approach. However it is not as efficient as the one already suggested in answers. Create a path vector for the node n1. Create a second path vector for the node n2. Path vector implying the set nodes from that one would traverse to reach the node in question. Compare both path vectors. The index where they mismatch, return the node at that index - 1. This would give the LCA. Cons for this approach: Need to traverse the tree twice for calculating the path vectors. Need addtional O(h) space to store path vectors. However this is easy to implement and understand as well. Code for calculating the path vector: private boolean findPathVector (TreeNode treeNode, int key, int pathVector[], int index) { if (treeNode == null) { return false; } pathVector [index++] = treeNode.getKey (); if (treeNode.getKey () == key) { return true; } if (findPathVector (treeNode.getLeftChild (), key, pathVector, index) || findPathVector (treeNode.getRightChild(), key, pathVector, index)) { return true; } pathVector [--index] = 0; return false; }
Try like this node * lca(node * root, int v1,int v2) { if(!root) { return NULL; } if(root->data == v1 || root->data == v2) { return root;} else { if((v1 > root->data && v2 < root->data) || (v1 < root->data && v2 > root->data)) { return root; } if(v1 < root->data && v2 < root->data) { root = lca(root->left, v1, v2); } if(v1 > root->data && v2 > root->data) { root = lca(root->right, v1, v2); } } return root; }
Crude way: At every node X = find if either of the n1, n2 exist on the left side of the Node Y = find if either of the n1, n2 exist on the right side of the Node if the node itself is n1 || n2, we can call it either found on left or right for the purposes of generalization. If both X and Y is true, then the Node is the CA The problem with the method above is that we will be doing the "find" multiple times, i.e. there is a possibility of each node getting traversed multiple times. We can overcome this problem if we can record the information so as to not process it again (think dynamic programming). So rather than doing find every node, we keep a record of as to whats already been found. Better Way: We check to see if for a given node if left_set (meaning either n1 | n2 has been found in the left subtree) or right_set in a depth first fashion. (NOTE: We are giving the root itself the property of being left_set if it is either n1 | n2) If both left_set and right_set then the node is a LCA. Code: struct Node * findCA(struct Node *root, struct Node *n1, struct Node *n2, int *set) { int left_set, right_set; left_set = right_set = 0; struct Node *leftCA, *rightCA; leftCA = rightCA = NULL; if (root == NULL) { return NULL; } if (root == n1 || root == n2) { left_set = 1; if (n1 == n2) { right_set = 1; } } if(!left_set) { leftCA = findCA(root->left, n1, n2, &left_set); if (leftCA) { return leftCA; } } if (!right_set) { rightCA= findCA(root->right, n1, n2, &right_set); if(rightCA) { return rightCA; } } if (left_set && right_set) { return root; } else { *set = (left_set || right_set); return NULL; } }
Code for A Breadth First Search to make sure both nodes are in the tree. Only then move forward with the LCA search. Please comment if you have any suggestions to improve. I think we can probably mark them visited and restart the search at a certain point where we left off to improve for the second node (if it isn't found VISITED) public class searchTree { static boolean v1=false,v2=false; public static boolean bfs(Treenode root, int value){ if(root==null){ return false; } Queue<Treenode> q1 = new LinkedList<Treenode>(); q1.add(root); while(!q1.isEmpty()) { Treenode temp = q1.peek(); if(temp!=null) { q1.remove(); if (temp.value == value) return true; if (temp.left != null) q1.add(temp.left); if (temp.right != null) q1.add(temp.right); } } return false; } public static Treenode lcaHelper(Treenode head, int x,int y){ if(head==null){ return null; } if(head.value == x || head.value ==y){ if (head.value == y){ v2 = true; return head; } else { v1 = true; return head; } } Treenode left = lcaHelper(head.left, x, y); Treenode right = lcaHelper(head.right,x,y); if(left!=null && right!=null){ return head; } return (left!=null) ? left:right; } public static int lca(Treenode head, int h1, int h2) { v1 = bfs(head,h1); v2 = bfs(head,h2); if(v1 && v2){ Treenode lca = lcaHelper(head,h1,h2); return lca.value; } return -1; } }
Some of the solutions here assumes that there is reference to the root node, some assumes that tree is a BST. Sharing my solution using hashmap, without reference to root node and tree can be BST or non-BST: var leftParent : Node? = left var rightParent : Node? = right var map = [data : Node?]() while leftParent != nil { map[(leftParent?.data)!] = leftParent leftParent = leftParent?.parent } while rightParent != nil { if let common = map[(rightParent?.data)!] { return common } rightParent = rightParent?.parent }
Solution 1: Recursive - Faster The idea is to traverse the tree starting from root. If any of the given keys p and q matches with root, then root is LCA, assuming that both keys are present. If root doesn’t match with any of the keys, we recurse for left and right subtree. The node which has one key present in its left subtree and the other key present in right subtree is the LCA. If both keys lie in left subtree, then left subtree has LCA also, otherwise LCA lies in right subtree. Time Complexity: O(n) Space Complexity: O(h) - for recursive call stack class Solution { public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { if(root == null || root == p || root == q) return root; TreeNode left = lowestCommonAncestor(root.left, p, q); TreeNode right = lowestCommonAncestor(root.right, p, q); if(left == null) return right; else if(right == null) return left; else return root; // If(left != null && right != null) } } Solution 2: Iterative - Using parent pointers - Slower Create an empty hash table. Insert p and all of its ancestors in hash table. Check if q or any of its ancestors exist in hash table, if yes then return the first existing ancestor. Time Complexity: O(n) - In the worst case we might be visiting all the nodes of binary tree. Space Complexity: O(n) - Space utilized the parent pointer Hash-table, ancestor_set and queue, would be O(n) each. class Solution { public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { HashMap<TreeNode, TreeNode> parent_map = new HashMap<>(); HashSet<TreeNode> ancestors_set = new HashSet<>(); Queue<TreeNode> queue = new LinkedList<>(); parent_map.put(root, null); queue.add(root); while(!parent_map.containsKey(p) || !parent_map.containsKey(q)) { TreeNode node = queue.poll(); if(node.left != null) { parent_map.put(node.left, node); queue.add(node.left); } if(node.right != null) { parent_map.put(node.right, node); queue.add(node.right); } } while(p != null) { ancestors_set.add(p); p = parent_map.get(p); } while(!ancestors_set.contains(q)) q = parent_map.get(q); return q; } }