Given a binary search tree, write a function kthSmallest to find the kth smallest element in it. (1 ≤ k ≤ BST’s total elements)
Java Solution 1 – Inorder Traversal
We can inorder traverse the tree and get the kth smallest element. Time is O(n).
public int kthSmallest(TreeNode root, int k) { Stack<TreeNode> stack = new Stack<TreeNode>(); TreeNode p = root; int result = 0; while(!stack.isEmpty() || p!=null){ if(p!=null){ stack.push(p); p = p.left; }else{ TreeNode t = stack.pop(); k--; if(k==0) result = t.val; p = t.right; } } return result; } |
Similarly, we can also write the inorder traversal as the following:
public int kthSmallest(TreeNode root, int k) { Stack<TreeNode> stack = new Stack<TreeNode>(); TreeNode p = root; while(p!=null){ stack.push(p); p=p.left; } int i=0; while(!stack.isEmpty()){ TreeNode t = stack.pop(); i++; if(i==k) return t.val; TreeNode r = t.right; while(r!=null){ stack.push(r); r=r.left; } } return -1; } |
Java Solution 2 – Extra Data Structure
We can let each node track the order, i.e., the number of elements that are less than itself. Time is O(log(n)).
public int find(TreeNode node, int k) {
if (node == null && k > 1) {
return -1;
}
if (node.getLeft() != null) {
find(node.getLeft(), k);
}
k--;
if (k == 1) {
return node.getValue();
}
if (node.getRight() != null) {
find(node.getRight(), k);
}
return -1;
}
recursive function requires call stack memory, which is limited to Operation System default. you will encounter stack overflow issue when call stack is full. In case of Windows, it’s limited to 1 MB. This restriction is defined by the designer of OS since Windows NT Data structure Stack class is only limited to actual RAM/external memory you have.
public int KthSmallest(TreeNode root, int k) {
int c=0;
int result=0;
KthSmallest(root,k,ref c,ref result);
return result;
}
public void KthSmallest(TreeNode root,int k, ref int c,ref int result)
{
if(root==null) return;
if(c>=k) return;
KthSmallest(root.left,k,ref c,ref result);
c++;
if(k==c){result= root.val; return;}
KthSmallest(root.right,k,ref c,ref result);
return;
}
there is a easier recursive implementation
TreeNode* kth(TreeNode *root, int & num, int k) {
if(!root) return NULL;
TreeNode *left = kth(root->left, num, k);
if(left) return left;
++num; //increment num everytime you visit a node in inorder traversal.
if(num == k) return root;
TreeNode *right = kth(root->right, num, k);
return right;
}
Different approach:
http://javabypatel.blogspot.in/2015/11/find-kth-smallest-element-in-binary-search-tree.html
I think below code will give the required result after in order traversal . Why do we need stack here ?
void findK(TreeNode root, int k) {
Treenode p = root ;
while(!p.isEmpty() || k >= 0)
{
findK(p.left, k);
–k;
if(k == 0) {
return p.val;
}
findK(p.right, k);
}
}
Correct me if I am wrong .
I think the program should return the result immediately after k equals 0, its unnecessary to keep on filling stack even after we have obtained our desired result. Please correct me if I’m wrong
https://www.youtube.com/watch?v=ufRadsWgxbA