Count smaller elements on Right side (original) (raw)
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
- [Expected Approach] Using Merge Sort - O(nlogn) Time and O(n) Space
[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.
C++ `
#include #include using namespace std;
vector constructLowerArray(vector& arr) { int n = arr.size(); vector 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& arr) { int n = arr.size(); for (int i = 0; i < n; i++) cout << arr[i] << " "; cout << "\n"; }
// Driver code int main() { vector arr = {12, 1, 2, 3, 0, 11, 4};
vector<int> low = constructLowerArray(arr);
printArray(low);
return 0;}
Java
import java.util.*;
class Main { static ArrayList constructLowerArray(int[] arr) { int n = arr.length; ArrayList 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);
}}
Python
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 countSmallerUtility 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)C#
using System; using System.Collections.Generic;
class Program { static List ConstructLowerArray(int[] arr) { int n = arr.Length; List countSmaller = new List(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);
}}
JavaScript
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);
`
[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. C++ `
#include <bits/stdc++.h> using namespace std;
void merge(vector<pair<int, int>>& v, vector& 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& 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 constructLowerArray(vector& 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& arr) { int n = arr.size(); for (int i = 0; i < n; i++) cout << arr[i] << " "; cout << "\n"; }
int main() { vector arr = {12, 1, 2, 3, 0, 11, 4};
vector<int> ans = constructLowerArray(arr);
printArray(ans);
return 0;}
Java
import java.util.*;
class GFG { static void merge(List<int[]> v, ArrayList 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);
}}
Python
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 ansUtility 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)
C#
using System; using System.Collections.Generic;
class GFG { static void Merge(List<int[]> v, List 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);
}}
JavaScript
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);
`