Find Surpasser Count of each element in array

3.6

A surpasser of an element of an array is a greater element to its right, therefore x[j] is a surpasser of x[i] if i < j and x[i] < x[j]. The surpasser count of an element is the number of surpassers. Given an array of distinct integers, for each element of the array find its surpasser count i.e. count the number of elements to the right that are greater than that element.

Examples:

Input:  [2, 7, 5, 3, 0, 8, 1]
Output: [4, 1, 1, 1, 2, 0, 0]

 

Method 1 (Naive)

The naive solution would be to run two loops. For each element of the array, we count all elements greater than it to its right. The complexity of this solution is O(n2)

// Naive C++ program to find surpasser count of
// each element in array
#include <bits/stdc++.h>
using namespace std;

// Function to find surpasser count of each element
// in array
void findSurpasser(int arr[], int n)
{
    for (int i = 0; i < n; i++)
    {
        // stores surpasser count for element arr[i]
        int count = 0;
        for (int j = i + 1; j < n; j++)
            if (arr[j] > arr[i])
                count++;

        cout << count << " ";
    }
}

/* Function to print an array */
void printArray(int arr[], int n)
{
    for (int i = 0; i < n; i++)
        printf("%d ", arr[i]);
    printf("\n");
}

/* Driver program to test above functions */
int main()
{
    int arr[] = { 2, 7, 5, 3, 0, 8, 1 };
    int n = sizeof(arr) / sizeof(arr[0]);

    printf("Given array is \n");
    printArray(arr, n);

    printf("Surpasser Count of array is \n");
    findSurpasser(arr, n);

    return 0;
}

Output:

Given array is 
2 7 5 3 0 8 1 
Surpasser Count of array is 
4 1 1 1 2 0 0

Time Complexity : O(n2)

Method 2 (Uses Merge Sort)

For any element of the array, we can easily find out number of elements to the right that are greater than that element if we know number of elements to its right that are less than that element. The idea is to count the number of inversions for each element of the array using merge sort. So, surpasser count of an element at position i will be equal to “n – i – inversion-count” at that position where n is the size of the array.

We have already discussed how to find inversion count of complete array here. We have modified the discussed approach to find number of inversions for each element of the array instead of returning inversion count of whole array. Also, as all elements of the array are distinct, we maintain a map that stores inversion count for each element of the array.

Below is C++ implementation of above idea –

// C++ program to find surpasser count of each element
// in array
#include <bits/stdc++.h>
using namespace std;

/* Function to merge the two haves arr[l..m] and
   arr[m+1..r] of array arr[] */
int merge(int arr[], int l, int m, int r,
          unordered_map<int, int> &hm)
{
    int i, j, k;
    int n1 = m - l + 1;
    int n2 = r - m;

    /* create temp arrays */
    int L[n1], R[n2];

    /* Copy data to temp arrays L[] and R[] */
    for (i = 0; i < n1; i++)
        L[i] = arr[l + i];

    for (j = 0; j < n2; j++)
        R[j] = arr[m + 1 + j];

    /* Merge the temp arrays back into arr[l..r]*/
    i = 0, j = 0, k = l;
    int c = 0;
    while (i < n1 && j < n2)
    {
        if (L[i] <= R[j])
        {
            // increment inversion count of L[i]
            hm[L[i]] += c;
            arr[k++] = L[i++];
        }
        else
        {
            arr[k++] = R[j++];

            // inversion found
            c++;
        }
    }

    /* Copy the remaining elements of L[], if
    there are any */
    while (i < n1)
    {
        hm[L[i]] += c;
        arr[k++] = L[i++];
    }

    /* Copy the remaining elements of R[], if
    there are any */
    while (j < n2)
        arr[k++] = R[j++];
}

/* l is for left index and r is right index of
the sub-array of arr to be sorted */
int mergeSort(int arr[], int l, int r,
              unordered_map<int, int> &hm)
{
    if (l < r)
    {
        int m = l + (r - l) / 2;
        mergeSort(arr, l, m, hm);
        mergeSort(arr, m + 1, r, hm);
        merge(arr, l, m, r, hm);
    }
}

/* Function to print an array */
void printArray(int arr[], int n)
{
    for (int i = 0; i < n; i++)
        printf("%d ", arr[i]);
    printf("\n");
}

void findSurpasser(int arr[], int n)
{
    // To store inversion count for elements
    unordered_map<int, int> hm;

    // To store copy of array
    int dup[n];
    memcpy(dup, arr, n*sizeof(arr[0]));

    // Sort the copy and store inversion count
    // for each element.
    mergeSort(dup, 0, n - 1, hm);

    printf("Surpasser Count of array is \n");
    for (int i = 0; i < n; i++)
        printf("%d ", (n - 1) - i - hm[arr[i]]);
}

/* Driver program to test above functions */
int main()
{
    int arr[] = { 2, 7, 5, 3, 0, 8, 1 };
    int n = sizeof(arr) / sizeof(arr[0]);

    printf("Given array is \n");
    printArray(arr, n);

    findSurpasser(arr, n);

    return 0;
}

Output:

Given array is 
2 7 5 3 0 8 1 
Surpasser Count of array is 
4 1 1 1 2 0 0

Time complexity of above solution is O(nlogn).

This article is contributed by Aditya Goel. If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above.

GATE CS Corner    Company Wise Coding Practice

Recommended Posts:



3.6 Average Difficulty : 3.6/5.0
Based on 34 vote(s)










Writing code in comment? Please use ide.geeksforgeeks.org, generate link and share the link here.