K'th Largest element in BST using constant extra space (original) (raw)

Last Updated : 11 Jul, 2025

Given a **Binary Search Tree (BST) and a positive integer **k, the task is to find the kth largest element in the Binary Search Tree.

**Example:

**Input: k = 3

th-Largest-element-in-BST

**Output: 14
**Explanation: If we sort the BST in decreasing order, then it will become 22, 20, 14, 12, 10, 8, 4. 14 is the 3rd largest element.

**Approach:

The idea is to use Reverse Morris Traversal which is based on Threaded Binary Trees. Threaded binary trees use the **NULL pointers to store the **successor and **predecessor information which helps us to utilize the wasted memory by those NULL pointers.

The special thing about Morris traversal is that we can do Inorder traversal without using **stack or **recursion which saves us memory consumed by stack or recursion call stack. Reverse Morris traversal is just the **reverse _of Morris traversal _which is majorly used to do Reverse Inorder traversal with **constant O(1) extra memory consumed as it does not uses any Stack or Recursion.

To find Kth largest element in a Binary search tree, the simplest logic is to do **reverse inorder traversal and while doing reverse inorder traversal simply keep a **count of number of Nodes visited. When the count becomes equal to **k, we stop the traversal and **print the data. It uses the fact that **reverse inorder traversal will give us a list sorted in descending order.

Below is the implementation of the above approach:

C++ `

// C++ Program to find kth largest element #include <bits/stdc++.h> using namespace std;

class Node { public: int data; Node *left; Node *right; Node(int x) { data = x; left = nullptr; right = nullptr; } };

// Function to perform Morris Traversal and // return kth largest element int kthLargest(Node* root, int k) {

// return -1 if root is null
if (root == nullptr) return -1;

Node* curr = root;
int cnt = 0;

while (curr != nullptr) {
    
    // if right tree does not exists,
    // then increment the count, check 
    // count==k. Otherwise, 
    // set curr = curr->left
    if (curr->right == nullptr) {
        cnt++;
        
        // return current Node
        // if cnt == k.
        if (cnt == k) 
            return curr->data;
            
        curr = curr->left;    
    }
    else {
        Node* succ = curr->right;
        
        // find the inorder successor
        while (succ->left != nullptr && 
               succ->left != curr) {
            succ = succ->left;
        }
        
        // create a linkage between succ and
        // curr 
        if (succ->left == nullptr) {
            succ->left = curr;
            curr = curr->right;
        }
        
        // if succ->left = curr, it means 
        // we have processed the right subtree,
        // and we can process curr node
        else {
            cnt++;  
            
            // remove the link 
            succ->left = nullptr;
            
            // return current Node
            // if cnt == k.
            if (cnt == k) 
                return curr->data;
            
            curr = curr->left;
        }
    }
}

return -1;

}

int main() {

// Create a hard coded tree.
//         20
//       /   \
//      8     22
//    /  \  
//   4   12  
//      /  \
//     10   14
Node* root = new Node(20);
root->left = new Node(8);
root->right = new Node(22);
root->left->left = new Node(4);
root->left->right = new Node(12);
root->left->right->left = new Node(10);
root->left->right->right = new Node(14);

int k = 3;

cout << kthLargest(root, k) << endl;

return 0;

}

C

// C Program to find kth largest element #include <stdio.h> #include <stdlib.h>

struct Node { int data; struct Node* left; struct Node* right; };

// Function to perform Morris Traversal and // return kth largest element int kthLargest(struct Node* root, int k) {

// return -1 if root is null
if (root == NULL) return -1;

struct Node* curr = root;
int cnt = 0;

while (curr != NULL) {

    // if right tree does not exist,
    // then increment the count, check 
    // count == k. Otherwise, 
    // set curr = curr->left
    if (curr->right == NULL) {
        cnt++;

        // return current Node
        // if cnt == k.
        if (cnt == k)
            return curr->data;

        curr = curr->left;
    } else {
        struct Node* succ = curr->right;

        // find the inorder successor
        while (succ->left != NULL && succ->left != curr) {
            succ = succ->left;
        }

        // create a linkage between pred and curr
        if (succ->left == NULL) {
            succ->left = curr;
            curr = curr->right;
        }

        // if succ->left = curr, it means 
        // we have processed the right subtree,
        // and we can process curr node
        else {
            cnt++;

            // remove the link
            succ->left = NULL;

            // return current Node
            // if cnt == k.
            if (cnt == k)
                return curr->data;

            curr = curr->left;
        }
    }
}

return -1;

}

struct Node* createNode(int x) { struct Node* node = (struct Node*)malloc(sizeof(struct Node)); node->data = x; node->left = NULL; node->right = NULL; return node; }

int main() {

// Create a hard-coded tree:
//         20
//       /   \
//      8     22
//    /  \
//   4   12
//      /  \
//     10   14
struct Node* root = createNode(20);
root->left = createNode(8);
root->right = createNode(22);
root->left->left = createNode(4);
root->left->right = createNode(12);
root->left->right->left = createNode(10);
root->left->right->right = createNode(14);

int k = 3;

printf("%d\n", kthLargest(root, k));

return 0;

}

Java

// Java Program to find kth largest element class Node { int data; Node left, right;

Node(int x) {
    data = x;
    left = right = null;
}

}

class GfG {

// Function to perform Morris Traversal 
// and return kth largest element
static int kthLargest(Node root, int k) {

    // return -1 if root is null
    if (root == null) return -1;

    Node curr = root;
    int cnt = 0;

    while (curr != null) {

        // if right tree does not exist,
        // then increment the count, check 
        // count == k. Otherwise, 
        // set curr = curr.left
        if (curr.right == null) {
            cnt++;

            // return current Node
            // if cnt == k.
            if (cnt == k) return curr.data;

            curr = curr.left;
        } else {
            Node succ = curr.right;

            // find the inorder successor
            while (succ.left != null && 
                   succ.left != curr) {
                succ = succ.left;
            }

            // create a linkage between succ and curr
            if (succ.left == null) {
                succ.left = curr;
                curr = curr.right;
            } else {
                cnt++;

                // remove the link
                succ.left = null;

                // return current Node
                // if cnt == k.
                if (cnt == k) return curr.data;

                curr = curr.left;
            }
        }
    }

    return -1;
}

public static void main(String[] args) {

    // Create a hard-coded tree:
    //         20
    //       /   \
    //      8     22
    //    /  \
    //   4   12
    //      /  \
    //     10   14
    Node root = new Node(20);
    root.left = new Node(8);
    root.right = new Node(22);
    root.left.left = new Node(4);
    root.left.right = new Node(12);
    root.left.right.left = new Node(10);
    root.left.right.right = new Node(14);

    int k = 3;

    System.out.println(kthLargest(root, k));
}

}

Python

Python Program to find kth largest element

class Node: def init(self, data): self.data = data self.left = None self.right = None

Function to perform Morris Traversal

and return kth largest element

def kth_largest(root, k):

# return -1 if root is null
if root is None:
    return -1

curr = root
cnt = 0

while curr is not None:

    # if right tree does not exist,
    # then increment the count, check 
    # count == k. Otherwise, 
    # set curr = curr.left
    if curr.right is None:
        cnt += 1

        # return current Node if cnt == k.
        if cnt == k:
            return curr.data

        curr = curr.left
    else:
        succ = curr.right

        # find the inorder successor
        while succ.left is not None and succ.left != curr:
            succ = succ.left

        # create a linkage between succ and curr
        if succ.left is None:
            succ.left = curr
            curr = curr.right
        else:
            cnt += 1

            # remove the link
            succ.left = None

            # return current Node if cnt == k.
            if cnt == k:
                return curr.data

            curr = curr.left

return -1

if name == "main":

# Create a hard-coded tree:
#         20
#       /   \
#      8     22
#    /  \
#   4   12
#      /  \
#     10   14
root = Node(20)
root.left = Node(8)
root.right = Node(22)
root.left.left = Node(4)
root.left.right = Node(12)
root.left.right.left = Node(10)
root.left.right.right = Node(14)

k = 3

print(kth_largest(root, k))

C#

// C# Program to find kth largest element using System;

class Node { public int data; public Node left, right;

public Node(int x) {
    data = x;
    left = right = null;
}

}

class GfG {

// Function to perform Morris Traversal and 
// return kth largest element
static int KthLargest(Node root, int k) {

    // return -1 if root is null
    if (root == null) return -1;

    Node curr = root;
    int cnt = 0;

    while (curr != null) {

        // if right tree does not exist,
        // then increment the count, check 
        // count == k. Otherwise, 
        // set curr = curr.left
        if (curr.right == null) {
            cnt++;

            // return current Node
            // if cnt == k
            if (cnt == k)
                return curr.data;

            curr = curr.left;
        } else {
            Node succ = curr.right;

            // find the inorder successor
            while (succ.left != null && succ.left != curr) {
                succ = succ.left;
            }

            // create a linkage between succ and curr
            if (succ.left == null) {
                succ.left = curr;
                curr = curr.right;
            } 
            
            // if succ.left == curr, it means 
            // we have processed the right subtree,
            // and we can process curr node
            else {
                cnt++;

                // remove the link 
                succ.left = null;

                // return current Node
                // if cnt == k
                if (cnt == k)
                    return curr.data;

                curr = curr.left;
            }
        }
    }

    return -1;
}

static void Main(string[] args) {

    // Create a hard-coded tree:
    //         20
    //       /   \
    //      8     22
    //    /  \
    //   4   12
    //      /  \
    //     10   14
    Node root = new Node(20);
    root.left = new Node(8);
    root.right = new Node(22);
    root.left.left = new Node(4);
    root.left.right = new Node(12);
    root.left.right.left = new Node(10);
    root.left.right.right = new Node(14);

    int k = 3;

    Console.WriteLine(KthLargest(root, k));
}

}

JavaScript

// JavaScript Program to find kth largest element class Node { constructor(data) { this.data = data; this.left = null; this.right = null; } }

// Function to perform Morris Traversal and // return kth largest element function kthLargest(root, k) {

// return -1 if root is null
if (root === null) return -1;

let curr = root;
let cnt = 0;

while (curr !== null) {

    // if right tree does not exist,
    // then increment the count, check 
    // count == k. Otherwise, 
    // set curr = curr.left
    if (curr.right === null) {
        cnt++;

        // return current Node
        // if cnt == k
        if (cnt === k)
            return curr.data;

        curr = curr.left;
    } else {
        let succ = curr.right;

        // find the inorder successor
        while (succ.left !== null && succ.left !== curr) {
            succ = succ.left;
        }

        // create a linkage between pred and curr
        if (succ.left === null) {
            succ.left = curr;
            curr = curr.right;
        } 
        
        // if succ.left == curr, it means 
        // we have processed the right subtree,
        // and we can process curr node
        else {
            cnt++;

            // remove the link 
            succ.left = null;

            // return current Node
            // if cnt == k
            if (cnt === k)
                return curr.data;

            curr = curr.left;
        }
    }
}

return -1;

}

// Create a hard-coded tree: // 20 // /
// 8 22 // /
// 4 12 // /
// 10 14 let root = new Node(20); root.left = new Node(8); root.right = new Node(22); root.left.left = new Node(4); root.left.right = new Node(12); root.left.right.left = new Node(10); root.left.right.right = new Node(14);

let k = 3;

console.log(kthLargest(root, k));

`

**Time Complexity: O(n), where n is the number of nodes in Binary tree.
**Auxiliary Space: O(1)