12. k-th Smallest in BST
The problem can be found at the following link: Question Link
Problem Description
Given a Binary Search Tree (BST) and an integer k, the task is to find the k-th smallest element in the BST.
If there is no k-th smallest element present, return -1
.
Examples
Example 1:
Input:
2
/ \
1 3
k = 2
Output:
2
Explanation:
The elements in ascending order are [1, 2, 3]
. The 2nd smallest element is 2
.
Example 2:
Input:
2
/ \
1 3
k = 5
Output:
-1
Explanation:
The BST contains only 3 elements. Hence, there is no 5th smallest element.
Example 3:
Input:
20
/ \
8 22
/ \
4 12
/ \
10 14
k = 3
Output:
10
Explanation:
The in-order traversal of the BST is [4, 8, 10, 12, 14, 20, 22]
.
The 3rd smallest element is 10
.
Constraints:
1 β€ number of nodes, k β€ $10^5$
1 β€ node->data β€ $10^5$
My Approach
Morris Inorder Traversal (O(1) Space)
Morris Traversal allows in-order traversal without using a stack or recursion, thus achieving O(1) space complexity.
It temporarily modifies the tree structure but restores it before completion.
Algorithm Steps:
Start from the root node.
If the left child is
NULL
:Visit the current node (decrement
k
).If
k == 0
, return the current node's value.Move to the right child.
If the left child exists:
Find the rightmost node in the left subtree (inorder predecessor).
If the rightmost node's right is
NULL
:Make the current node its right child (create a temporary thread).
Move to the left child.
If the rightmost nodeβs right is the current node (thread exists):
Remove the thread (restore the original tree).
Visit the current node (decrement
k
).If
k == 0
, return the current node's value.Move to the right child.
If the traversal completes without finding the k-th smallest, return
-1
.
Time and Auxiliary Space Complexity
Expected Time Complexity:
O(N)
We visit each node exactly twice (once to create a thread and once to remove it), which is linear with respect to the number of nodes.Expected Auxiliary Space Complexity:
O(1)
No additional stack or recursion is used. Only a few pointers are manipulated.
Code (C)
int kthSmallest(struct Node* root, int k) {
while (root) {
if (!root->left) {
if (--k == 0) return root->data;
root = root->right;
} else {
struct Node *pre = root->left;
while (pre->right && pre->right != root) pre = pre->right;
if (!pre->right) {
pre->right = root;
root = root->left;
} else {
pre->right = NULL;
if (--k == 0) return root->data;
root = root->right;
}
}
}
return -1;
}
Code (C++)
class Solution {
public:
int kthSmallest(Node* root, int k) {
while (root) {
if (!root->left) {
if (--k == 0) return root->data;
root = root->right;
} else {
Node* pre = root->left;
while (pre->right && pre->right != root) pre = pre->right;
if (!pre->right) {
pre->right = root;
root = root->left;
} else {
pre->right = NULL;
if (--k == 0) return root->data;
root = root->right;
}
}
}
return -1;
}
};
Code (Java)
class Solution {
public int kthSmallest(Node root, int k) {
while (root != null) {
if (root.left == null) {
if (--k == 0) return root.data;
root = root.right;
} else {
Node pre = root.left;
while (pre.right != null && pre.right != root) pre = pre.right;
if (pre.right == null) {
pre.right = root;
root = root.left;
} else {
pre.right = null;
if (--k == 0) return root.data;
root = root.right;
}
}
}
return -1;
}
}
Code (Python)
class Solution:
def kthSmallest(self, root, k):
while root:
if not root.left:
k -= 1
if k == 0:
return root.data
root = root.right
else:
pre = root.left
while pre.right and pre.right != root:
pre = pre.right
if not pre.right:
pre.right = root
root = root.left
else:
pre.right = None
k -= 1
if k == 0:
return root.data
root = root.right
return -1
Contribution and Support
For discussions, questions, or doubts related to this solution, feel free to connect on LinkedIn: Any Questions. Letβs make this learning journey more collaborative!
β If you find this helpful, please give this repository a star! β
πVisitor Count
Last updated