18. Median of BST
β GFG solution to the Median of BST problem: find median element in a BST using space-efficient Morris Traversal technique without recursion or stack. π
The problem can be found at the following link: π Question Link
π§© Problem Description
You are given the root of a Binary Search Tree (BST). Your task is to find the median of the BST.
When the nodes of the BST are written in ascending order (inorder traversal) as Vβ, Vβ, Vβ, β¦, Vβ, where n is the total number of nodes:
If n is odd: return Vβββββ/β
If n is even: return Vβ/β
π Examples
Example 1
Input: root = [20, 8, 22, 4, 12, N, N, N, N, 10, 14]
Output: 12
Explanation: The inorder of given BST is 4, 8, 10, 12, 14, 20, 22.
Here, n = 7 (odd), so median will be ((7+1)/2)th value = 4th value = 12.
Example 2
Input: root = [5, 4, 8, 1]
Output: 4
Explanation: The inorder of given BST is 1, 4, 5, 8.
Here, n = 4 (even), so median will be (4/2)th value = 2nd value = 4.
π Constraints
$1 \le \text{number of nodes} \le 10^5$
$1 \le \text{node.data} \le 10^5$
β
My Approach
The optimal approach uses Morris Traversal - a space-efficient method that performs inorder traversal without using recursion or stack:
Morris Traversal Technique
First Pass - Count Total Nodes:
Traverse the tree using Morris Traversal algorithm.
Count all nodes while traversing without using extra space.
Morris Traversal temporarily modifies tree structure to create threading.
Calculate Median Position:
Based on total count
n
, calculate median indexk = (n + 1) / 2
.This formula works for both odd and even number of nodes.
Second Pass - Find Median:
Perform Morris Traversal again to reach the kth element.
Track current position during traversal.
Return the value when position matches median index.
Morris Traversal Details:
For each node, if left child doesn't exist, visit node and move right.
If left child exists, find inorder predecessor (rightmost node in left subtree).
Create temporary thread from predecessor to current node.
Follow the thread and break it after visiting to restore tree structure.
π Time and Auxiliary Space Complexity
Expected Time Complexity: O(n), where n is the number of nodes in the BST. Morris Traversal visits each edge at most twice - once to create the thread and once to traverse it, resulting in O(n) operations overall despite appearing to have nested loops.
Expected Auxiliary Space Complexity: O(1), as Morris Traversal uses only a constant amount of extra space (a few pointers) and doesn't require recursion stack or auxiliary data structures. The tree structure is temporarily modified but restored during traversal.
π§βπ» Code (C++)
class Solution {
public:
int findMedian(Node* root) {
int n = 0, k = 0, med = -1;
Node* c = root;
while (c) {
if (!c->left) { n++; c = c->right; }
else {
Node* p = c->left;
while (p->right && p->right != c) p = p->right;
if (!p->right) { p->right = c; c = c->left; }
else { p->right = nullptr; n++; c = c->right; }
}
}
k = (n + 1) / 2;
c = root;
while (c) {
if (!c->left) {
if (++med == k - 1) return c->data;
c = c->right;
} else {
Node* p = c->left;
while (p->right && p->right != c) p = p->right;
if (!p->right) { p->right = c; c = c->left; }
else {
p->right = nullptr;
if (++med == k - 1) return c->data;
c = c->right;
}
}
}
return -1;
}
};
β Code (Java)
class Solution {
public int findMedian(Node root) {
int n = 0, k = 0, med = -1;
Node c = root;
while (c != null) {
if (c.left == null) { n++; c = c.right; }
else {
Node p = c.left;
while (p.right != null && p.right != c) p = p.right;
if (p.right == null) { p.right = c; c = c.left; }
else { p.right = null; n++; c = c.right; }
}
}
k = (n + 1) / 2;
c = root;
while (c != null) {
if (c.left == null) {
if (++med == k - 1) return c.data;
c = c.right;
} else {
Node p = c.left;
while (p.right != null && p.right != c) p = p.right;
if (p.right == null) { p.right = c; c = c.left; }
else {
p.right = null;
if (++med == k - 1) return c.data;
c = c.right;
}
}
}
return -1;
}
}
π Code (Python)
class Solution:
def findMedian(self, root):
n, c = 0, root
while c:
if not c.left:
n += 1
c = c.right
else:
p = c.left
while p.right and p.right != c:
p = p.right
if not p.right:
p.right = c
c = c.left
else:
p.right = None
n += 1
c = c.right
k, med, c = (n + 1) // 2, -1, root
while c:
if not c.left:
med += 1
if med == k - 1:
return c.data
c = c.right
else:
p = c.left
while p.right and p.right != c:
p = p.right
if not p.right:
p.right = c
c = c.left
else:
p.right = None
med += 1
if med == k - 1:
return c.data
c = c.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