Count smaller elements on Right side
Given an unsorted array arr[] of distinct integers, construct another array countSmaller[] such that countSmaller[i] contains the count of smaller elements on the right side of each element arr[i] in the array.
Examples:
Input: arr[] = [12, 1, 2, 3, 0, 11, 4]
Output: [6, 1, 1, 1, 0, 1, 0]Input: arr[] = [5, 4, 3, 2, 1]
Output: [4, 3, 2, 1, 0]Input: arr[] = [1, 2, 3, 4, 5]
Output: [0, 0, 0, 0, 0]
Table of Content
[Naive Approach] Using Nested Loop - O(n*n) Time and O(n) Space
The idea is to use nested loops, where for each element we check how many elements on its right side are smaller than it.
#include <iostream>
#include <vector>
using namespace std;
vector<int> constructLowerArray(vector<int>& arr) {
int n = arr.size();
vector<int> countSmaller(n, 0);
int i, j;
// Check for every element how many elements on right side are smaller
for (i = 0; i < n; i++) {
for (j = i + 1; j < n; j++) {
if (arr[j] < arr[i])
countSmaller[i]++;
}
}
return countSmaller;
}
// Utility function that prints out an array on a line
void printArray(vector<int>& arr) {
int n = arr.size();
for (int i = 0; i < n; i++)
cout << arr[i] << " ";
cout << "\n";
}
// Driver code
int main() {
vector<int> arr = {12, 1, 2, 3, 0, 11, 4};
vector<int> low = constructLowerArray(arr);
printArray(low);
return 0;
}
import java.util.*;
class Main {
static ArrayList<Integer> constructLowerArray(int[] arr) {
int n = arr.length;
ArrayList<Integer> countSmaller = new ArrayList<>(Collections.nCopies(n, 0));
// Check for every element how many elements on right side are smaller
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
if (arr[j] < arr[i])
countSmaller.set(i, countSmaller.get(i) + 1);
}
}
return countSmaller;
}
// Utility function that prints out an array on a line
static void printArray(ArrayList<Integer> arr) {
for (int x : arr)
System.out.print(x + " ");
System.out.println();
}
public static void main(String[] args) {
int[] arr = {12, 1, 2, 3, 0, 11, 4};
ArrayList<Integer> low = constructLowerArray(arr);
printArray(low);
}
}
def constructLowerArray(arr):
n = len(arr)
countSmaller = [0] * n
# Check for every element how many elements on right side are smaller
for i in range(n):
for j in range(i + 1, n):
if arr[j] < arr[i]:
countSmaller[i] += 1
return countSmaller
# Utility function that prints out an array on a line
def printArray(arr):
for x in arr:
print(x, end=" ")
print()
if __name__ =="__main__":
arr = [12, 1, 2, 3, 0, 11, 4]
low = constructLowerArray(arr)
printArray(low)
using System;
using System.Collections.Generic;
class Program {
static List<int> ConstructLowerArray(int[] arr) {
int n = arr.Length;
List<int> countSmaller = new List<int>(new int[n]);
// Check for every element how many elements on right side are smaller
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
if (arr[j] < arr[i])
countSmaller[i]++;
}
}
return countSmaller;
}
// Utility function that prints out an array on a line
static void PrintArray(List<int> arr) {
foreach (int x in arr)
Console.Write(x + " ");
Console.WriteLine();
}
static void Main() {
int[] arr = {12, 1, 2, 3, 0, 11, 4};
List<int> low = ConstructLowerArray(arr);
PrintArray(low);
}
}
function constructLowerArray(arr) {
let n = arr.length;
let countSmaller = new Array(n).fill(0);
// Check for every element how many elements on right side are smaller
for (let i = 0; i < n; i++) {
for (let j = i + 1; j < n; j++) {
if (arr[j] < arr[i])
countSmaller[i]++;
}
}
return countSmaller;
}
// Utility function that prints out an array on a line
function printArray(arr) {
console.log(arr.join(" "));
}
// Driver code
let arr = [12, 1, 2, 3, 0, 11, 4];
let low = constructLowerArray(arr);
printArray(low);
Output
6 1 1 1 0 1 0
[Expected Approach] Using Merge Sort - O(nlogn) Time and O(n) Space
The idea is to use a modified merge sort. We store both element values and their original indices. While merging, we count how many elements from the right half are smaller and add this count to the corresponding index’s result.
Steps to solve the problem:
- Store each element with its index in a pair (value, index).
- Perform merge sort on this pair array.
- During merging: check if a left element is greater than a right element.
- If yes, then all remaining elements in the right half are smaller → add their count to the result of that left element’s index.
- After counting, place elements into the merged array.
- Otherwise, merge normally when the left element is not greater.
- Continue recursively until the entire array is sorted.
- The result array will finally hold the number of smaller elements on the right for each index.
#include <bits/stdc++.h>
using namespace std;
void merge(vector<pair<int, int>>& v, vector<int>& ans, int l, int mid, int h) {
// temporary array for merging both halves
vector<pair<int, int>> t;
int i = l;
int j = mid + 1;
while (i < mid + 1 && j <= h) {
// v[i].first is greater than
// all the elements from j till h.
if (v[i].first > v[j].first) {
ans[v[i].second] += (h - j + 1);
t.push_back(v[i]);
i++;
} else {
t.push_back(v[j]);
j++;
}
}
// if any elements left in left array
while (i <= mid)
t.push_back(v[i++]);
// if any elements left in right array
while (j <= h)
t.push_back(v[j++]);
// putting elements back in main array
// in descending order
for (int k = 0, idx = l; idx <= h; idx++, k++)
v[idx] = t[k];
}
void mergesort(vector<pair<int, int>>& v, vector<int>& ans, int i, int j) {
if (i < j) {
int mid = (i + j) / 2;
// calling mergesort for left half
mergesort(v, ans, i, mid);
// calling mergesort for right half
mergesort(v, ans, mid + 1, j);
// merging both halves and generating answer
merge(v, ans, i, mid, j);
}
}
vector<int> constructLowerArray(vector<int>& arr) {
int n = arr.size();
vector<pair<int, int>> v;
// inserting elements and corresponding index as pair
for (int i = 0; i < n; i++)
v.push_back({arr[i], i});
// answer array for keeping count initialized by 0
vector<int> ans(n, 0);
// calling mergesort
mergesort(v, ans, 0, n - 1);
return ans;
}
// Utility function to print an array
void printArray(vector<int>& arr) {
int n = arr.size();
for (int i = 0; i < n; i++)
cout << arr[i] << " ";
cout << "\n";
}
int main() {
vector<int> arr = {12, 1, 2, 3, 0, 11, 4};
vector<int> ans = constructLowerArray(arr);
printArray(ans);
return 0;
}
import java.util.*;
class GFG {
static void merge(List<int[]> v, ArrayList<Integer> ans, int l, int mid, int h) {
// temporary array for merging both halves
List<int[]> t = new ArrayList<>();
int i = l, j = mid + 1;
while (i < mid + 1 && j <= h) {
// v.get(i)[0] is greater than all
// the elements from j till h
if (v.get(i)[0] > v.get(j)[0]) {
ans.set(v.get(i)[1], ans.get(v.get(i)[1]) + (h - j + 1));
t.add(v.get(i));
i++;
} else {
t.add(v.get(j));
j++;
}
}
// if any elements left in left array
while (i <= mid) t.add(v.get(i++));
// if any elements left in right array
while (j <= h) t.add(v.get(j++));
// putting elements back in main array in descending order
for (int k = 0, idx = l; idx <= h; idx++, k++)
v.set(idx, t.get(k));
}
static void mergesort(List<int[]> v, ArrayList<Integer> ans, int i, int j) {
if (i < j) {
int mid = (i + j) / 2;
// calling mergesort for left half
mergesort(v, ans, i, mid);
// calling mergesort for right half
mergesort(v, ans, mid + 1, j);
// merging both halves and generating answer
merge(v, ans, i, mid, j);
}
}
static ArrayList<Integer> constructLowerArray(int[] arr) {
int n = arr.length;
List<int[]> v = new ArrayList<>();
// inserting elements and corresponding index as pair
for (int i = 0; i < n; i++)
v.add(new int[]{arr[i], i});
// answer array for keeping count initialized by 0
ArrayList<Integer> ans = new ArrayList<>(Collections.nCopies(n, 0));
// calling mergesort
mergesort(v, ans, 0, n - 1);
return ans;
}
// Utility function to print an array
static void printArray(ArrayList<Integer> arr) {
for (int x : arr) System.out.print(x + " ");
System.out.println();
}
public static void main(String[] args) {
int[] arr = {12, 1, 2, 3, 0, 11, 4};
ArrayList<Integer> ans = constructLowerArray(arr);
printArray(ans);
}
}
def merge(v, ans, l, mid, h):
t = [] # temporary array for merging both halves
i, j = l, mid + 1
while i < mid + 1 and j <= h:
# v[i][0] is greater than all the elements from j till h
if v[i][0] > v[j][0]:
ans[v[i][1]] += (h - j + 1)
t.append(v[i])
i += 1
else:
t.append(v[j])
j += 1
# if any elements left in left array
while i <= mid:
t.append(v[i]); i += 1
# if any elements left in right array
while j <= h:
t.append(v[j]); j += 1
# putting elements back in main array in descending order
for k, idx in enumerate(range(l, h + 1)):
v[idx] = t[k]
def mergesort(v, ans, i, j):
if i < j:
mid = (i + j) // 2
# calling mergesort for left half
mergesort(v, ans, i, mid)
# calling mergesort for right half
mergesort(v, ans, mid + 1, j)
# merging both halves and generating answer
merge(v, ans, i, mid, j)
def constructLowerArray(arr):
n = len(arr)
# inserting elements and corresponding index as pair
v = [(arr[i], i) for i in range(n)]
# answer array for keeping count initialized by 0
ans = [0] * n
# calling mergesort
mergesort(v, ans, 0, n - 1)
return ans
# Utility function to print an array
def printArray(arr):
print(" ".join(map(str, arr)))
if __name__ =="__main__":
arr = [12, 1, 2, 3, 0, 11, 4]
ans = constructLowerArray(arr)
printArray(ans)
using System;
using System.Collections.Generic;
class GFG {
static void Merge(List<int[]> v, List<int> ans, int l, int mid, int h) {
List<int[]> t = new List<int[]>(); // temporary array for merging both halves
int i = l, j = mid + 1;
while (i < mid + 1 && j <= h) {
// v[i][0] is greater than all the elements from j till h
if (v[i][0] > v[j][0]) {
ans[v[i][1]] += (h - j + 1);
t.Add(v[i]);
i++;
} else {
t.Add(v[j]);
j++;
}
}
// if any elements left in left array
while (i <= mid) t.Add(v[i++]);
// if any elements left in right array
while (j <= h) t.Add(v[j++]);
// putting elements back in main array in descending order
for (int k = 0, idx = l; idx <= h; idx++, k++)
v[idx] = t[k];
}
static void MergeSort(List<int[]> v, List<int> ans, int i, int j) {
if (i < j) {
int mid = (i + j) / 2;
// calling mergesort for left half
MergeSort(v, ans, i, mid);
// calling mergesort for right half
MergeSort(v, ans, mid + 1, j);
// merging both halves and generating answer
Merge(v, ans, i, mid, j);
}
}
static List<int> ConstructLowerArray(int[] arr) {
int n = arr.Length;
List<int[]> v = new List<int[]>();
// inserting elements and corresponding index as pair
for (int i = 0; i < n; i++)
v.Add(new int[] { arr[i], i });
// answer array for keeping count initialized by 0
List<int> ans = new List<int>(new int[n]);
// calling mergesort
MergeSort(v, ans, 0, n - 1);
return ans;
}
// Utility function to print an array
static void PrintArray(List<int> arr) {
foreach (int x in arr)
Console.Write(x + " ");
Console.WriteLine();
}
static void Main() {
int[] arr = { 12, 1, 2, 3, 0, 11, 4 };
List<int> ans = ConstructLowerArray(arr);
PrintArray(ans);
}
}
function merge(v, ans, l, mid, h) {
let t = []; // temporary array for merging both halves
let i = l, j = mid + 1;
while (i < mid + 1 && j <= h) {
// v[i][0] is greater than all the elements from j till h
if (v[i][0] > v[j][0]) {
ans[v[i][1]] += (h - j + 1);
t.push(v[i]);
i++;
} else {
t.push(v[j]);
j++;
}
}
// if any elements left in left array
while (i <= mid) t.push(v[i++]);
// if any elements left in right array
while (j <= h) t.push(v[j++]);
// putting elements back in main array in descending order
for (let k = 0, idx = l; idx <= h; idx++, k++)
v[idx] = t[k];
}
function mergesort(v, ans, i, j) {
if (i < j) {
let mid = Math.floor((i + j) / 2);
// calling mergesort for left half
mergesort(v, ans, i, mid);
// calling mergesort for right half
mergesort(v, ans, mid + 1, j);
// merging both halves and generating answer
merge(v, ans, i, mid, j);
}
}
function constructLowerArray(arr) {
let n = arr.length;
// inserting elements and corresponding index as pair
let v = [];
for (let i = 0; i < n; i++)
v.push([arr[i], i]);
// answer array for keeping count initialized by 0
let ans = new Array(n).fill(0);
// calling mergesort
mergesort(v, ans, 0, n - 1);
return ans;
}
// Utility function to print an array
function printArray(arr) {
console.log(arr.join(" "));
}
// Driver code
let arr = [12, 1, 2, 3, 0, 11, 4];
let ans = constructLowerArray(arr);
printArray(ans);
Output
6 1 1 1 0 1 0