Rank of elements in a stream
Last Updated :
24 Feb, 2025
Given a stream of integers, the task is to find the rank of each integer in the stream. Rank of an element x is defined as the number of distinct values less than x.
Example:
Input : arr[] = [5, 1, 4, 4, 5, 9, 7, 13, 3]
Output : 0 0 1 1 2 3 3 5 1
Explanation:
- 5 arrives: rank = 0 (no elements less than 5)
- 1 arrives: rank = 0 (no elements less than 1)
- 4 arrives: rank = 1 (one distinct element (1) less than 4)
- 4 arrives: rank = 1 (one distinct element (1) less than 4)
- 5 arrives: rank = 2 (two distinct elements (1, 4) less than 5)
- 9 arrives: rank = 3 (three distinct elements (1, 4, 5) less than 9)
- 7 arrives: rank = 3 (three distinct elements (1, 4, 5) less than 7)
- 13 arrives: rank = 5 (five distinct elements (1, 4, 5, 7, 9) less than 13)
- 3 arrives: rank = 1 (one distinct element (1) less than 3)
[Naive Approach] Using Array and Hash Set- O(n^2) time and O(n) space
The idea is to store each element in an array. For every new element traverse through the array and store distinct smaller values in a hash set. The size of set will give the rank of the current element.
C++
// C++ program to find the rank
// of elements in a stream.
#include <iostream>
#include <vector>
#include <unordered_set>
using namespace std;
class Solution{
public:
vector<int> arr;
int findRank(int x) {
// Insert the value into the array.
arr.push_back(x);
unordered_set<int> set;
// Find the number of distinct
// values less than x.
for (auto val: arr) {
if (val < x) {
set.insert(val);
}
}
// Size of set will give the
// rank of x.
return set.size();
}
};
int main() {
Solution* s = new Solution();
vector<int> arr = {5, 1, 4, 4, 5, 9, 7, 13, 3};
for (int i=0; i<arr.size(); i++) {
int rank = s->findRank(arr[i]);
cout << rank << " ";
}
cout << endl;
return 0;
}
Java
// Java program to find the rank
// of elements in a stream.
import java.util.*;
class Solution {
ArrayList<Integer> arr = new ArrayList<>();
int findRank(int x) {
// Insert the value into the array.
arr.add(x);
HashSet<Integer> set = new HashSet<>();
// Find the number of distinct
// values less than x.
for (int val : arr) {
if (val < x) {
set.add(val);
}
}
// Size of set will give the
// rank of x.
return set.size();
}
}
class GfG {
public static void main(String[] args) {
Solution s = new Solution();
ArrayList<Integer> arr = new ArrayList<>(
Arrays.asList(5, 1, 4, 4, 5, 9, 7, 13, 3)
);
for (int i = 0; i < arr.size(); i++) {
int rank = s.findRank(arr.get(i));
System.out.print(rank + " ");
}
System.out.println();
}
}
Python
# Python program to find the rank
# of elements in a stream.
class Solution:
def __init__(self):
self.arr = []
def findRank(self, x):
# Insert the value into the array.
self.arr.append(x)
unique_values = set()
# Find the number of distinct
# values less than x.
for val in self.arr:
if val < x:
unique_values.add(val)
# Size of set will give the
# rank of x.
return len(unique_values)
if __name__ == "__main__":
s = Solution()
arr = [5, 1, 4, 4, 5, 9, 7, 13, 3]
for i in range(len(arr)):
rank = s.findRank(arr[i])
print(rank, end=" ")
print()
C#
// C# program to find the rank
// of elements in a stream.
using System;
using System.Collections.Generic;
class Solution {
List<int> arr = new List<int>();
public int findRank(int x) {
// Insert the value into the array.
arr.Add(x);
HashSet<int> set = new HashSet<int>();
// Find the number of distinct
// values less than x.
foreach (int val in arr) {
if (val < x) {
set.Add(val);
}
}
// Size of set will give the
// rank of x.
return set.Count;
}
}
class GfG {
static void Main(string[] args) {
Solution s = new Solution();
List<int> arr = new List<int> {5, 1, 4, 4, 5, 9, 7, 13, 3};
for (int i = 0; i < arr.Count; i++) {
int rank = s.findRank(arr[i]);
Console.Write(rank + " ");
}
Console.WriteLine();
}
}
JavaScript
// JavaScript program to find the rank
// of elements in a stream.
class Solution {
constructor() {
this.arr = [];
}
findRank(x) {
// Insert the value into the array.
this.arr.push(x);
let set = new Set();
// Find the number of distinct
// values less than x.
for (let val of this.arr) {
if (val < x) {
set.add(val);
}
}
// Size of set will give the
// rank of x.
return set.size;
}
}
let s = new Solution();
let arr = [5, 1, 4, 4, 5, 9, 7, 13, 3];
for (let i = 0; i < arr.length; i++) {
let rank = s.findRank(arr[i]);
process.stdout.write(rank + " ");
}
console.log();
[Expected Approach] Using Binary Search Tree
The idea is to maintain a Binary Search Tree (BST) where each node keeps track of the count of nodes in its left subtree, allowing us to find the rank (number of distinct smaller elements) of any value in O(log n) time.
Step by step approach:
- When a new value arrives, first check if it already exists in the BST by traversing and keeping track of smaller elements
- If value exists, return its rank (the count of distinct smaller elements found during traversal)
- If value doesn't exist, insert it into the BST while incrementing leftCount of nodes when going left and adding leftCount+1 when going right
- During insertion of a new value, maintain a running sum of smaller elements (rank) by adding leftCount+1 whenever we go right
C++
// C++ program to find the rank
// of elements in a stream.
#include <iostream>
#include <vector>
using namespace std;
class Node {
public:
int data;
Node* left;
Node* right;
int leftCount;
Node(int value) {
data = value;
left = right = nullptr;
leftCount = 0;
}
};
class Solution {
private:
Node* root;
// Returns rank if value exists, -1 if it doesn't
int findRank(Node* node, int val) {
if (node == nullptr) return -1;
if (val == node->data) {
return node->leftCount;
}
else if (val < node->data) {
return findRank(node->left, val);
}
else {
int rightRank = findRank(node->right, val);
if (rightRank == -1) return -1;
return node->leftCount + 1 + rightRank;
}
}
Node* insertNew(Node* node, int val, int& rank) {
if (node == nullptr) {
return new Node(val);
}
if (val < node->data) {
node->leftCount++;
node->left = insertNew(node->left, val, rank);
}
else {
rank += node->leftCount + 1;
node->right = insertNew(node->right, val, rank);
}
return node;
}
public:
Solution() {
root = nullptr;
}
int findRank(int val) {
// First check if value already exists
int existingRank = findRank(root, val);
if (existingRank != -1) {
return existingRank;
}
// If value doesn't exist, insert it
int rank = 0;
root = insertNew(root, val, rank);
return rank;
}
};
int main() {
Solution *s = new Solution();
vector<int> arr = {5, 1, 4, 4, 5, 9, 7, 13, 3};
for (int i = 0; i < arr.size(); i++) {
int rank = s->findRank(arr[i]);
cout << rank << " ";
}
cout << endl;
return 0;
}
Java
// Java program to find the rank
// of elements in a stream.
class Node {
int data;
Node left;
Node right;
int leftCount;
Node(int value) {
data = value;
left = right = null;
leftCount = 0;
}
}
class Solution {
private Node root;
Solution() {
root = null;
}
// Returns rank if value exists, -1 if it doesn't
static int findRank(Node node, int val) {
if (node == null) return -1;
if (val == node.data) {
return node.leftCount;
} else if (val < node.data) {
return findRank(node.left, val);
} else {
int rightRank = findRank(node.right, val);
if (rightRank == -1) return -1;
return node.leftCount + 1 + rightRank;
}
}
static Node insertNew(Node node, int val, int[] rank) {
if (node == null) {
return new Node(val);
}
if (val < node.data) {
node.leftCount++;
node.left = insertNew(node.left, val, rank);
} else {
rank[0] += node.leftCount + 1;
node.right = insertNew(node.right, val, rank);
}
return node;
}
int findRank(int val) {
// First check if value already exists
int existingRank = findRank(root, val);
if (existingRank != -1) {
return existingRank;
}
// If value doesn't exist, insert it
int[] rank = {0};
root = insertNew(root, val, rank);
return rank[0];
}
}
class GfG {
public static void main(String[] args) {
Solution s = new Solution();
int[] arr = {5, 1, 4, 4, 5, 9, 7, 13, 3};
for (int i = 0; i < arr.length; i++) {
int rank = s.findRank(arr[i]);
System.out.print(rank + " ");
}
System.out.println();
}
}
Python
# Python program to find the rank
# of elements in a stream.
class Node:
def __init__(self, value):
self.data = value
self.left = None
self.right = None
self.leftCount = 0
class Solution:
def __init__(self):
self.root = None
# Returns rank if value exists, -1 if it doesn't
def findRankHelper(self, node, val):
if node is None:
return -1
if val == node.data:
return node.leftCount
elif val < node.data:
return self.findRankHelper(node.left, val)
else:
rightRank = self.findRankHelper(node.right, val)
if rightRank == -1:
return -1
return node.leftCount + 1 + rightRank
def insertNew(self, node, val, rank):
if node is None:
return Node(val)
if val < node.data:
node.leftCount += 1
node.left = self.insertNew(node.left, val, rank)
else:
rank[0] += node.leftCount + 1
node.right = self.insertNew(node.right, val, rank)
return node
def findRank(self, val):
# First check if value already exists
existingRank = self.findRankHelper(self.root, val)
if existingRank != -1:
return existingRank
# If value doesn't exist, insert it
rank = [0]
self.root = self.insertNew(self.root, val, rank)
return rank[0]
if __name__ == "__main__":
s = Solution()
arr = [5, 1, 4, 4, 5, 9, 7, 13, 3]
for num in arr:
rank = s.findRank(num)
print(rank, end=" ")
print()
C#
// C# program to find the rank
// of elements in a stream.
using System;
class Node {
public int data;
public Node left;
public Node right;
public int leftCount;
public Node(int value) {
data = value;
left = right = null;
leftCount = 0;
}
}
class Solution {
private Node root;
public Solution() {
root = null;
}
// Returns rank if value exists, -1 if it doesn't
static int findRank(Node node, int val) {
if (node == null) return -1;
if (val == node.data) {
return node.leftCount;
} else if (val < node.data) {
return findRank(node.left, val);
} else {
int rightRank = findRank(node.right, val);
if (rightRank == -1) return -1;
return node.leftCount + 1 + rightRank;
}
}
static Node insertNew(Node node, int val, ref int rank) {
if (node == null) {
return new Node(val);
}
if (val < node.data) {
node.leftCount++;
node.left = insertNew(node.left, val, ref rank);
} else {
rank += node.leftCount + 1;
node.right = insertNew(node.right, val, ref rank);
}
return node;
}
public int findRank(int val) {
// First check if value already exists
int existingRank = findRank(root, val);
if (existingRank != -1) {
return existingRank;
}
// If value doesn't exist, insert it
int rank = 0;
root = insertNew(root, val, ref rank);
return rank;
}
}
class GfG {
static void Main() {
Solution s = new Solution();
int[] arr = {5, 1, 4, 4, 5, 9, 7, 13, 3};
for (int i = 0; i < arr.Length; i++) {
int rank = s.findRank(arr[i]);
Console.Write(rank + " ");
}
Console.WriteLine();
}
}
JavaScript
// JavaScript program to find the rank
// of elements in a stream.
class Node {
constructor(value) {
this.data = value;
this.left = null;
this.right = null;
this.leftCount = 0;
}
}
class Solution {
constructor() {
this.root = null;
}
// Returns rank if value exists, -1 if it doesn't
findRankHelper(node, val) {
if (node === null) return -1;
if (val === node.data) {
return node.leftCount;
} else if (val < node.data) {
return this.findRankHelper(node.left, val);
} else {
let rightRank = this.findRankHelper(node.right, val);
if (rightRank === -1) return -1;
return node.leftCount + 1 + rightRank;
}
}
insertNew(node, val, rank) {
if (node === null) {
return new Node(val);
}
if (val < node.data) {
node.leftCount++;
node.left = this.insertNew(node.left, val, rank);
} else {
rank[0] += node.leftCount + 1;
node.right = this.insertNew(node.right, val, rank);
}
return node;
}
findRank(val) {
// First check if value already exists
let existingRank = this.findRankHelper(this.root, val);
if (existingRank !== -1) {
return existingRank;
}
// If value doesn't exist, insert it
let rank = [0];
this.root = this.insertNew(this.root, val, rank);
return rank[0];
}
}
let s = new Solution();
let arr = [5, 1, 4, 4, 5, 9, 7, 13, 3];
for (let i = 0; i < arr.length; i++) {
let rank = s.findRank(arr[i]);
console.log(rank + " ");
}
Further Optimization : Note that the time complexity of findRank is O(h) where h is height of the BST. The height might become O(n) in worst case. Instead of using a normal BST, we need to use a Self-Balancing BST like AVL Tree or Red Black Tree. With these trees, we get the findRank operation in O(Log n).
Time Complexity: O(n * log n) assuming a self balancing BST implementation, where n is the number of elements in the stream. For each element, it will take O(log n) time to check if element is present and to insert the element in to the tree.
Auxiliary Space: O(n), due to Binary Search Tree.
Explore
DSA Fundamentals
Data Structures
Algorithms
Advanced
Interview Preparation
Practice Problem