Given a BST, the task is to find the sum of all elements greater than or equal to K-th largest element in O(1) space.
Examples:
Input : K = 3
8
/ \
7 10
/ / \
2 9 13
Output : 32
Explanation: 3rd largest element is 9 so sum of all
elements greater than or equal to 9 are
9 + 10 + 13 = 32.
Input : K = 2
8
/ \
5 11
/ \
2 7
\
3
Output : 19
Explanation: 2nd largest element is 8 so sum of all
elements greater than or equal to 8 are
8 + 11 = 19.
Approach: The approach here is to do reverse inorder traversal, and while doing it simply keep a count of the number of nodes visited. Until the count of visited nodes is less than equal to K, keep on adding the current node’s data. Use the fact that the reverse inorder traversal of a BST gives us a list that is sorted in decreasing order. But recursion or stack/queue-based approach to do reverse inorder traversal because both these techniques consume O(n) extra memory, instead make use of Reverse Morris Traversal to do inorder tree traversal, which is a memory-efficient and faster method to do reverse inorder tree traversal based on threaded binary trees.
Given below is the algorithm:
1) Initialize Current as root.
2) Initialize a "count" and "sum" variable to 0.
3) While current is not NULL :
3.1) If the current has no right child
a) Increment count and check if count is less than or equal to K.
1) Simply add the current node's data in "sum" variable.
b) Otherwise, Move to the left child of current.
3.2) Else, here we have 2 cases:
a) Find the inorder successor of current Node.
Inorder successor is the left most Node
in the right subtree or right child itself.
b) If the left child of the inorder successor is NULL:
1) Set current as the left child of its inorder successor.
2) Move current Node to its right child.
c) Else, if the threaded link between the current Node
and it's inorder successor already exists :
1) Set left pointer of the inorder successor as NULL.
2) Increment count and check if the count is less than or equal to K.
2.a) Simply add the current node's data in "sum" variable.
3) Otherwise, Move current to it's left child.
4)After the traversal is complete simply return the sum.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
struct node {
int data;
struct node *left, *right;
};
node* newNode( int item)
{
node* temp = new node;
temp->data = item;
temp->left = temp->right = NULL;
return temp;
}
int SumKLargestUsingReverseMorrisTraversal(node* root, int k)
{
node* curr = root;
int sum = 0;
int count = 0;
while (curr) {
if (curr->right == NULL) {
if (++count <= k) {
sum += curr->data;
}
curr = curr->left;
}
else {
node* succ = curr->right;
while (succ->left && succ->left != curr)
succ = succ->left;
if (succ->left == NULL) {
succ->left = curr;
curr = curr->right;
}
else {
succ->left = NULL;
if (++count <= k)
sum += curr->data;
curr = curr->left;
}
}
}
return sum;
}
int main()
{
struct node* root = newNode(8);
root->right = newNode(10);
root->left = newNode(7);
root->left->left = newNode(2);
root->right->left = newNode(9);
root->right->right = newNode(13);
cout << SumKLargestUsingReverseMorrisTraversal(root, 3);
return 0;
}
|
Java
class GFG
{
static class node
{
int data;
node left, right;
};
static node newNode( int item)
{
node temp = new node();
temp.data = item;
temp.left = temp.right = null ;
return temp;
}
static int SumKLargestUsingReverseMorrisTraversal(node root, int k)
{
node curr = root;
int sum = 0 ;
int count = 0 ;
while (curr != null )
{
if (curr.right == null )
{
if (++count <= k)
{
sum += curr.data;
}
curr = curr.left;
}
else
{
node succ = curr.right;
while (succ.left != null && succ.left != curr)
succ = succ.left;
if (succ.left == null )
{
succ.left = curr;
curr = curr.right;
}
else
{
succ.left = null ;
if (++count <= k)
sum += curr.data;
curr = curr.left;
}
}
}
return sum;
}
public static void main(String[] args)
{
node root = newNode( 8 );
root.right = newNode( 10 );
root.left = newNode( 7 );
root.left.left = newNode( 2 );
root.right.left = newNode( 9 );
root.right.right = newNode( 13 );
System.out.println(SumKLargestUsingReverseMorrisTraversal(root, 3 ));
}
}
|
Python3
class node:
def __init__( self , data):
self .data = data
self .left = None
self .right = None
def newNode(item):
temp = node(item)
return temp
def SumKLargestUsingReverseMorrisTraversal(root, k):
curr = root
sum = 0
count = 0
while (curr):
if (curr.right = = None ):
count + = 1
if (count < = k):
sum + = curr.data
curr = curr.left
else :
succ = curr.right
while (succ.left and
succ.left ! = curr):
succ = succ.left
if (succ.left = = None ):
succ.left = curr
curr = curr.right
else :
succ.left = None
count + = 1
if (count < = k):
sum + = curr.data
curr = curr.left
return sum
if __name__ = = "__main__" :
root = newNode( 8 )
root.right = newNode( 10 )
root.left = newNode( 7 )
root.left.left = newNode( 2 )
root.right.left = newNode( 9 )
root.right.right = newNode( 13 )
print (SumKLargestUsingReverseMorrisTraversal(root, 3 ))
|
C#
using System;
class GFG
{
public class node
{
public int data;
public node left, right;
};
static node newNode( int item)
{
node temp = new node();
temp.data = item;
temp.left = temp.right = null ;
return temp;
}
static int SumKLargestUsingReverseMorrisTraversal(node root, int k)
{
node curr = root;
int sum = 0;
int count = 0;
while (curr != null )
{
if (curr.right == null )
{
if (++count <= k)
{
sum += curr.data;
}
curr = curr.left;
}
else
{
node succ = curr.right;
while (succ.left != null && succ.left != curr)
succ = succ.left;
if (succ.left == null )
{
succ.left = curr;
curr = curr.right;
}
else
{
succ.left = null ;
if (++count <= k)
sum += curr.data;
curr = curr.left;
}
}
}
return sum;
}
public static void Main(String[] args)
{
node root = newNode(8);
root.right = newNode(10);
root.left = newNode(7);
root.left.left = newNode(2);
root.right.left = newNode(9);
root.right.right = newNode(13);
Console.WriteLine(SumKLargestUsingReverseMorrisTraversal(root, 3));
}
}
|
Javascript
<script>
class node
{
constructor()
{
this .data = 0;
this .left = this .right = null ;
}
}
function newNode(item)
{
let temp = new node();
temp.data = item;
temp.left = temp.right = null ;
return temp;
}
function SumKLargestUsingReverseMorrisTraversal(root,k)
{
let curr = root;
let sum = 0;
let count = 0;
while (curr != null )
{
if (curr.right == null )
{
if (++count <= k)
{
sum += curr.data;
}
curr = curr.left;
}
else
{
let succ = curr.right;
while (succ.left != null && succ.left != curr)
succ = succ.left;
if (succ.left == null )
{
succ.left = curr;
curr = curr.right;
}
else
{
succ.left = null ;
if (++count <= k)
sum += curr.data;
curr = curr.left;
}
}
}
return sum;
}
let root = newNode(8);
root.right = newNode(10);
root.left = newNode(7);
root.left.left = newNode(2);
root.right.left = newNode(9);
root.right.right = newNode(13);
document.write(SumKLargestUsingReverseMorrisTraversal(root, 3));
</script>
|
Time Complexity: O(N)
Space complexity: O(1)
Feeling lost in the world of random DSA topics, wasting time without progress? It's time for a change! Join our DSA course, where we'll guide you on an exciting journey to master DSA efficiently and on schedule.
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 geeks!