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

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 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)

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:

#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 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)

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);

`