Open In App

Count number of pairs with the given Comparator

Given an array arr[], the task is to count the number of pairs (arr[i], arr[j]) on the right of every element with any custom comparator. 

Comparator can be of any type, some of them are given below –  

arr[i] > arr[j],    where i < j
arr[i] < arr[j],    where i  2 * arr[j], where i < j

Examples:  

Input: arr[] = {5, 4, 3, 2, 1}, comp = arr[i] > arr[j] 
Output: 10 
Explanation: 
There are 10 such pairs, in which right element is smaller than the left element – 
{(5, 4), (5, 3), (5, 2), (5, 1), (4, 3), (4, 2), (4, 1), (3, 2), (3, 1), (2, 1)} 

Input: arr[] = {3, 4, 3}, comp = arr[i] == arr[j] 
Output:
Explanation: 
There is only one such pair such that elements are equal. That is (3, 3) 

Recommended: Please try your approach on {IDE} first, before moving on to the solution.

Naive Solution: Iterate over every pairs of the elements, such that i < j and check for each pair that the custom comparator is true or not. If yes, then increment the count.
Time Complexity: O(N2)

Efficient Approach: The idea is to customize merge sort, to compute such pairs at the time of merging two sub-arrays. There will be two types of count for every array that is –  

For Left subarrays, the count can be calculated recursively from bottom to top whereas the main task will be to count the intra-array pairs.

Therefore, Total such pairs can be defined as – 

Total Pairs = Inter-Array pairs in Left Sub-array +
      Inter-Array pairs in Right Sub-array +
      Intra-Array pairs from left to right sub-array 

Below is the illustration of the intra-array pairs of the array from left sub-array to right sub-array – 

if start1 == end1 and start2 == end2:
    if compare(arr, start1, start2):
        c += 1

Therefore, These all the three cases can be calculated individually for such pairs.

if compare(arr, start1, start2):
    count += end1 - start1 + 1
if compare(arr, start1, start2):
    count += end2 - start2 + 1
if compare(arr, start1, start2):
    while compare(arr, start1, start2):
        count += 1
        start1 += 1

Below is the implementation of the above approach: 




// C++ implementation to find the 
// elements on the right with the given 
// custom comparator 
  
#include <bits/stdc++.h>
  
using namespace std;
  
// comparator to check 
// if two elements are equal 
bool compare(int arr[], int s1, int s2){
    if (arr[s1] > arr[s2]){
        return true;
    }
    else{
        return false;
    }
}
  
// Function to find the Intra-Array 
// Count in the two subarrays 
int findIntraArrayCount(int arr[], int s1,
       int e1, int s2, int e2, int g){
             
    // Base Case
    if (s1 == e1 && s2 == e2){
        int c = 0;
        if (compare(arr, s1, s2)){
            c += 1;
        }
        if (arr[s1] > arr[s2]){
            int temp = arr[s1];
            arr[s1] = arr[s2];
            arr[s2] = temp;
        }
        return c;
    }
      
    // Variable for keeping 
    // the count of the pair
    int c = 0;
    int s = s1, e = e2, s3 = s1;
    int e3 = e1, s4 = s2, e4 = e2;
      
    while (s1 <= e1 && s2 <= e2){
          
        // Condition when we have to use the 
        // Greater than comparator 
        if (g == 1){
            if (compare(arr, s1, s2)){
                c += e1 - s1 + 1;
                s2 += 1;
            }
            else{
                s1 += 1;
            }
        }
          
        // Condition when we have to use the 
        // Less than comparator
        else if (g == 0){
            if (compare(arr, s1, s2)){
                c += e2 - s2 + 1;
                s1 += 1;
            }
            else {
                s2 += 1;
            }
        }
          
        // Condition when we have to use the 
        // Equal to Comparator 
        else if (g == -1){
            if (compare(arr, s1, s2)){
                int c1 = 0;
                while (s1 <= e1 && 
                       compare(arr, s1, s2)){
                    c1 += 1;
                    s1 += 1;
                }
                s1 -= 1;
                int c2 = 0;
                while (s2 <= e2 && 
                       compare(arr, s1, s2)){
                    c2 += 1;
                    s2 += 1;
                }
                c += c1 * c2;
            }
            else {
                if (arr[s1] > arr[s2]){
                    s2 += 1;
                }
                else{
                    s1 += 1;
                }
            }
        }
    }
    s1 = s3; e1 = e3;
    s2 = s4; e2 = e4;
      
    // Array to store 
    // the sorted subarray
    vector<int> aux;
      
    // Merge the two subarrays
    while (s1 <= e1 && s2 <= e2){
        if (arr[s1] <= arr[s2]){
            aux.push_back(arr[s1]);
            s1 += 1;
        }
        else{
            aux.push_back(arr[s2]);
            s2 += 1;
        }
    }
      
    // Copy subarray 1 elements 
    while (s1 <= e1){
        aux.push_back(arr[s1]);
        s1 += 1;
    }
      
    // Copy subarray 2 elements 
    while (s2 <= e2){
        aux.push_back(arr[s2]);
        s2 += 1;
    }
      
    // Update the original array
    for (int i = s; i <= e; i++){
        arr[i] = aux[i-s];
    }
    return c;
}
  
// Function to find such pairs with 
// any custom comparator function 
int findElementsOnRight(int arr[], int s,
                           int e, int g){
    if (s >= e){
        return 0;
    }
    int mid = (s+e)/2;
      
    // Recursive call for inter-array 
    // count of pairs in left subarrays
    int c1 = findElementsOnRight(
                      arr, s, mid, g);
      
    // Recursive call for inter-array 
    // count of pairs in right sub-arrays 
    int c2 = findElementsOnRight(
                   arr, mid + 1, e, g);
      
    // Call for intra-array pairs 
    int c3 = findIntraArrayCount(
              arr, s, mid, mid+1, e, g);
      
    return c1 + c2 + c3;
}
  
  
// Driver code
int main()
{
    int arr[] = {4, 3, 2, 1};
    int g = 1;
    cout << findElementsOnRight(arr, 0, 3, g);
    return 0;
}




// Java implementation to find the 
// elements on the right with the given 
// custom comparator 
  
import java.io.*;
import java.lang.*;
import java.util.*;
  
class GFG {
      
    // comparator to check 
    // if two elements are equal 
    public static boolean compare(
          int[] arr, int s1, int s2){
        if (arr[s1] > arr[s2]){
            return true;
        }
        else{
            return false;
        }
    }
      
    // Function to find the Intra-Array 
    // Count in the two subarrays 
    public static int findIntraArrayCount(
        int[] arr, int s1, int e1, int s2, 
                           int e2, int g){
                                 
        // Base Case
        if (s1 == e1 && s2 == e2){
            int c = 0;
            if (compare(arr, s1, s2)){
                c += 1;
            }
            if (arr[s1] > arr[s2]){
                int temp = arr[s1];
                arr[s1] = arr[s2];
                arr[s2] = temp;
            }
            return c;
        }
          
        // Variable for keeping 
        // the count of the pair
        int c = 0;
        int s = s1, e = e2, s3 = s1;
        int e3 = e1, s4 = s2, e4 = e2;
          
        while (s1 <= e1 && s2 <= e2){
              
            // Condition when we have to use the 
            // Greater than comparator
            if (g == 1){
                if (compare(arr, s1, s2)){
                    c += e1 - s1 + 1;
                    s2 += 1;
                }
                else{
                    s1 += 1;
                }
            }
              
            // Condition when we have to use the 
            // Equal to Comparator 
            else if (g == 0){
                if (compare(arr, s1, s2)){
                    c += e2 - s2 + 1;
                    s1 += 1;
                }
                else {
                    s2 += 1;
                }
            }
              
            // Condition when we have to use the 
            // Equal to Comparator 
            else if (g == -1){
                if (compare(arr, s1, s2)){
                    int c1 = 0;
                    while (s1 <= e1 && 
                         compare(arr, s1, s2)){
                        c1 += 1;
                        s1 += 1;
                    }
                    s1 -= 1;
                    int c2 = 0;
                    while (s2 <= e2 && 
                          compare(arr, s1, s2)){
                        c2 += 1;
                        s2 += 1;
                    }
                    c += c1 * c2;
                }
                else {
                    if (arr[s1] > arr[s2]){
                        s2 += 1;
                    }
                    else{
                        s1 += 1;
                    }
                }
            }
        }
        s1 = s3; e1 = e3;
        s2 = s4; e2 = e4;
          
        // Array to store 
        // the sorted subarray
        ArrayList<Integer> aux = 
                     new ArrayList<>();
                       
        // Merge the two subarrays
        while (s1 <= e1 && s2 <= e2){
            if (arr[s1] <= arr[s2]){
                aux.add(arr[s1]);
                s1 += 1;
            }
            else{
                aux.add(arr[s2]);
                s2 += 1;
            }
        }
          
        // Copy subarray 1 elements 
        while (s1 <= e1){
            aux.add(arr[s1]);
            s1 += 1;
        }
          
        // Copy subarray 2 elements
        while (s2 <= e2){
            aux.add(arr[s2]);
            s2 += 1;
        }
          
        // Update the original array
        for (int i = s; i <= e; i++){
            arr[i] = aux.get(i-s);
        }
        return c;
    }
      
    // Function to find such pairs with 
    // any custom comparator function 
    public static int findElementsOnRight(
        int[] arr, int s, int e, int g){
        if (s >= e){
            return 0;
        }
        int mid = (s+e)/2;
          
        // Recursive call for inter-array 
        // count of pairs in left subarrays
        int c1 = findElementsOnRight(arr, s, 
                                     mid, g);
          
        // Recursive call for inter-array 
        // count of pairs in right sub-arrays 
        int c2 = findElementsOnRight(arr, mid + 1
                                         e, g);
          
        // Call for intra-array pairs 
        int c3 = findIntraArrayCount(arr, s, 
                            mid, mid+1, e, g);
          
        return c1 + c2 + c3;                                   
    }
      
    // Driver code
    public static void main (String[] args) {
        int[] arr = {4, 3, 2, 1};
        int g = 1;
        System.out.println(
            findElementsOnRight(arr, 0, 3, g));
    }
}




# Python3 implementation to find the 
# elements on the right with the given 
# custom comparator 
  
import random, math 
from copy import deepcopy as dc 
  
# comparator to check 
# if two elements are equal 
def compare(arr, s1, s2): 
    if arr[s1] > arr[s2]: 
        return True
    else
        return False
  
  
# Function to find the Intra-Array 
# Count in the two subarrays 
def findIntraArrayCount(arr, s1, \
                e1, s2, e2, g): 
      
    # Base Case 
    if s1 == e1 and s2 == e2: 
        c = 0
        if compare(arr, s1, s2): 
            c += 1
        if arr[s1] > arr[s2]: 
            arr[s1], arr[s2] = arr[s2], arr[s1] 
        return
  
  
    # Variable for keeping 
    # the count of the pair 
    c = 0
      
    # Total subarray length 
    s = dc(s1); e = dc(e2) 
      
    # length of subarray 1 
    s3 = dc(s1); e3 = dc(e1) 
      
    # length of subarray 2 
    s4 = dc(s2); e4 = dc(e2) 
      
    while s1 <= e1 and s2 <= e2: 
  
  
        # Condition when we have to use the 
        # Greater than comparator 
        if g == 1
            if compare(arr, s1, s2): 
                c += e1 - s1 + 1
                s2 += 1
            else
                s1 += 1
  
        # Condition when we have to use the 
        # Less than comparator 
        elif g == 0
            if compare(arr, s1, s2): 
                c += e2 - s2 + 1
                s1 += 1
            else
                s2 += 1
                  
        # Condition when we have to use the 
        # Equal to Comparator 
        elif g == -1
            if compare(arr, s1, s2):
                c1 = 0
                while s1 <= e1 and\
                   compare(arr, s1, s2): 
                    c1 += 1
                    s1 += 1
                s1 -= 1
                c2 = 0
                while s2 <= e2 and\
                    compare(arr, s1, s2):
                    c2 += 1
                    s2 += 1
                c += c1 * c2
            else
                if arr[s1] > arr[s2]:
                    s2 += 1
                else:
                    s1 += 1
  
    s1 = dc(s3); e1 = dc(e3) 
      
    s2 = dc(s4); e2 = dc(e4) 
      
    # Array to store the sorted subarray 
    aux = [] 
      
      
    # Merge the two subarrays 
    while s1 <= e1 and s2 <= e2: 
        if arr[s1] <= arr[s2]: 
            aux.append(arr[s1]) 
            s1 += 1
        else
            aux.append(arr[s2]) 
            s2 += 1
      
    # Copy subarray 1 elements 
    while s1 <= e1: 
        aux.append(arr[s1]) 
        s1 += 1
          
      
    # Copy subarray 2 elements 
    while s2 <= e2: 
        aux.append(arr[s2]) 
        s2 += 1
          
      
    # Update the original array 
    for i in range(s, e + 1): 
        arr[i] = aux[i-s] 
    return
  
  
  
# Function to find such pairs with 
# any custom comparator function 
def findElementsOnRight(arr, s, e, g): 
    if s >= e: 
        return 0
    mid = (s + e)//2
      
    # Recursive call for inter-array 
    # count of pairs in left subarrays 
    c1 = findElementsOnRight(arr, s, \
                            mid, g) 
      
    # Recursive call for inter-array 
    # count of pairs in right sub-arrays 
    c2 = findElementsOnRight(arr, mid + 1, \
                                e, g) 
      
    # Call for intra-array pairs 
    c3 = findIntraArrayCount(arr, s, mid, \
                            mid + 1, e, g) 
    return c1 + c2 + c3 
  
  
  
  
# Driver Code 
if __name__ == "__main__"
    arr = [4, 3, 2, 1]
    g = 1
    out = findElementsOnRight(arr, 0, \
                        len(arr)-1, g) 
    print(out) 




// C# implementation to find the  
// elements on the right with the
// given custom comparator  
using System;
using System.Collections.Generic;
  
class GFG{
      
// comparator to check  
// if two elements are equal  
public static bool compare(int[] arr, int s1,
                                      int s2)
    if (arr[s1] > arr[s2])
    
        return true
    
    else
    
        return false
    
    
// Function to find the Intra-Array  
// Count in the two subarrays  
public static int findIntraArrayCount(int[] arr, int s1,
                                      int e1, int s2,  
                                      int e2, int g)
      
    // Base Case 
    if (s1 == e1 && s2 == e2)
    
        int cc = 0; 
        if (compare(arr, s1, s2))
        
            cc += 1; 
        
        if (arr[s1] > arr[s2])
        
            int temp = arr[s1]; 
            arr[s1] = arr[s2]; 
            arr[s2] = temp; 
        
        return cc; 
    
        
    // Variable for keeping  
    // the count of the pair 
    int c = 0; 
    int s = s1, e = e2, s3 = s1; 
    int e3 = e1, s4 = s2, e4 = e2; 
        
    while (s1 <= e1 && s2 <= e2)
    
          
        // Condition when we have to use the  
        // Greater than comparator 
        if (g == 1)
        
            if (compare(arr, s1, s2))
            
                c += e1 - s1 + 1; 
                s2 += 1; 
            
            else
            
                s1 += 1; 
            
        
            
        // Condition when we have to use the  
        // Equal to Comparator  
        else if (g == 0)
        
            if (compare(arr, s1, s2))
            
                c += e2 - s2 + 1; 
                s1 += 1; 
            
            else 
            
                s2 += 1; 
            
        
            
        // Condition when we have to use the  
        // Equal to Comparator  
        else if (g == -1)
        
            if (compare(arr, s1, s2))
            
                int c1 = 0; 
                while (s1 <= e1 &&  
                       compare(arr, s1, s2))
                
                    c1 += 1; 
                    s1 += 1; 
                
                s1 -= 1; 
                int c2 = 0; 
                while (s2 <= e2 &&  
                       compare(arr, s1, s2))
                
                    c2 += 1; 
                    s2 += 1; 
                
                c += c1 * c2; 
            
            else
            
                if (arr[s1] > arr[s2])
                
                    s2 += 1; 
                
                else
                
                    s1 += 1; 
                
            
        
    
    s1 = s3; e1 = e3; 
    s2 = s4; e2 = e4; 
        
    // Array to store  
    // the sorted subarray 
    List<int> aux = new List<int>(); 
                     
    // Merge the two subarrays 
    while (s1 <= e1 && s2 <= e2)
    
        if (arr[s1] <= arr[s2])
        
            aux.Add(arr[s1]); 
            s1 += 1; 
        
        else
        
            aux.Add(arr[s2]); 
            s2 += 1; 
        
    
        
    // Copy subarray 1 elements  
    while (s1 <= e1)
    
        aux.Add(arr[s1]); 
        s1 += 1; 
    
        
    // Copy subarray 2 elements 
    while (s2 <= e2)
    
        aux.Add(arr[s2]); 
        s2 += 1; 
    
        
    // Update the original array 
    for(int i = s; i <= e; i++)
    
        arr[i] = aux[i-s]; 
    
    return c; 
    
// Function to find such pairs with  
// any custom comparator function  
public static int findElementsOnRight(int[] arr, int s, 
                                      int e, int g)
    if (s >= e)
    {
        return 0; 
    
    int mid = (s + e) / 2; 
        
    // Recursive call for inter-array  
    // count of pairs in left subarrays 
    int c1 = findElementsOnRight(arr, s,  
                                 mid, g); 
        
    // Recursive call for inter-array  
    // count of pairs in right sub-arrays  
    int c2 = findElementsOnRight(arr, mid + 1,  
                                   e, g); 
        
    // Call for intra-array pairs  
    int c3 = findIntraArrayCount(arr, s, mid, 
                                 mid + 1, e, g); 
        
    return c1 + c2 + c3;                                    
  
// Driver code
static public void Main()
{
    int[] arr = { 4, 3, 2, 1 }; 
    int g = 1; 
      
    Console.WriteLine(findElementsOnRight(
        arr, 0, 3, g)); 
}
}
  
// This code is contributed by offbeat




<script>
// Javascript implementation to find the
// elements on the right with the given
// custom comparator
  
  
// comparator to check
// if two elements are equal
function compare(arr, s1, s2) {
    if (arr[s1] > arr[s2]) {
        return true;
    }
    else {
        return false;
    }
}
  
// Function to find the Intra-Array
// Count in the two subarrays
function findIntraArrayCount(arr, s1, e1, s2, e2, g) {
  
    // Base Case
    if (s1 == e1 && s2 == e2) {
        let c = 0;
        if (compare(arr, s1, s2)) {
            c += 1;
        }
        if (arr[s1] > arr[s2]) {
            let temp = arr[s1];
            arr[s1] = arr[s2];
            arr[s2] = temp;
        }
        return c;
    }
  
    // Variable for keeping
    // the count of the pair
    let c = 0;
    let s = s1, e = e2, s3 = s1;
    let e3 = e1, s4 = s2, e4 = e2;
  
    while (s1 <= e1 && s2 <= e2) {
  
        // Condition when we have to use the
        // Greater than comparator
        if (g == 1) {
            if (compare(arr, s1, s2)) {
                c += e1 - s1 + 1;
                s2 += 1;
            }
            else {
                s1 += 1;
            }
        }
  
        // Condition when we have to use the
        // Less than comparator
        else if (g == 0) {
            if (compare(arr, s1, s2)) {
                c += e2 - s2 + 1;
                s1 += 1;
            }
            else {
                s2 += 1;
            }
        }
  
        // Condition when we have to use the
        // Equal to Comparator
        else if (g == -1) {
            if (compare(arr, s1, s2)) {
                let c1 = 0;
                while (s1 <= e1 &&
                    compare(arr, s1, s2)) {
                    c1 += 1;
                    s1 += 1;
                }
                s1 -= 1;
                let c2 = 0;
                while (s2 <= e2 &&
                    compare(arr, s1, s2)) {
                    c2 += 1;
                    s2 += 1;
                }
                c += c1 * c2;
            }
            else {
                if (arr[s1] > arr[s2]) {
                    s2 += 1;
                }
                else {
                    s1 += 1;
                }
            }
        }
    }
    s1 = s3; e1 = e3;
    s2 = s4; e2 = e4;
  
    // Array to store
    // the sorted subarray
    let aux = new Array();
  
    // Merge the two subarrays
    while (s1 <= e1 && s2 <= e2) {
        if (arr[s1] <= arr[s2]) {
            aux.push(arr[s1]);
            s1 += 1;
        }
        else {
            aux.push(arr[s2]);
            s2 += 1;
        }
    }
  
    // Copy subarray 1 elements
    while (s1 <= e1) {
        aux.push(arr[s1]);
        s1 += 1;
    }
  
    // Copy subarray 2 elements
    while (s2 <= e2) {
        aux.push(arr[s2]);
        s2 += 1;
    }
  
    // Update the original array
    for (let i = s; i <= e; i++) {
        arr[i] = aux[i - s];
    }
    return c;
}
  
// Function to find such pairs with
// any custom comparator function
function findElementsOnRight(arr, s, e, g) {
    if (s >= e) {
        return 0;
    }
    let mid = Math.floor((s + e) / 2);
  
    // Recursive call for inter-array
    // count of pairs in left subarrays
    let c1 = findElementsOnRight(
        arr, s, mid, g);
  
    // Recursive call for inter-array
    // count of pairs in right sub-arrays
    let c2 = findElementsOnRight(
        arr, mid + 1, e, g);
  
    // Call for intra-array pairs
    let c3 = findIntraArrayCount(
        arr, s, mid, mid + 1, e, g);
  
    return c1 + c2 + c3;
}
  
  
// Driver code
  
let arr = [4, 3, 2, 1];
let g = 1;
document.write(findElementsOnRight(arr, 0, 3, g));
  
  
// This code is contributed by gfgking
</script>

Output: 
6

 

Time Complexity: The above method takes O(N*logN) time.
Auxiliary Space: O(N)
 


Article Tags :