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: 1
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 –
- Inter-Array Pairs: Pairs those are present in the left subarray itself.
- Intra-Array Pairs: Pairs those are present in the right subarray.
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 –
- Base Case: The base case for this problem will be when there is only one element in the two sub-arrays and we wanted to check the intra-array pairs. Then, check that those two elements form one such pair then increment the count and also place the smaller element at its position.
if start1 == end1 and start2 == end2:
if compare(arr, start1, start2):
c += 1
- Recursive Case: This problem can be divided into three types on the basis of the comparator function –
- When comparison operator between pairs is of greater than or equal to.
- When comparison operator between pairs is of less than or equal to.
- When comparison operator between pairs is equal to.
Therefore, These all the three cases can be calculated individually for such pairs.
- Case 1: In case greater than or equal to, if we find any such pair then all the elements to right of that subarray will also form pair with the current element. Due to which the count of such pairs is incremented by the number of elements left in the left sub-array.
if compare(arr, start1, start2):
count += end1 - start1 + 1
- Case 2: In case less than or equal to, if we find any such pair then all the elements to right of that subarray will also form pair with the current element. Due to which the count of such pairs is incremented by the number of elements left in the right sub-array.
if compare(arr, start1, start2):
count += end2 - start2 + 1
- Case 3: In case equal to, If we find any such pair, then we try to find all such pairs possible in the left subarray with the help of a while loop. In each such possible pair increment the count by 1.
if compare(arr, start1, start2):
while compare(arr, start1, start2):
count += 1
start1 += 1
- Finally, Merge the two subarrays as it is done in the merge sort.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
bool compare( int arr[], int s1, int s2){
if (arr[s1] > arr[s2]){
return true ;
}
else {
return false ;
}
}
int findIntraArrayCount( int arr[], int s1,
int e1, int s2, int e2, int g){
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;
}
int c = 0;
int s = s1, e = e2, s3 = s1;
int e3 = e1, s4 = s2, e4 = e2;
while (s1 <= e1 && s2 <= e2){
if (g == 1){
if (compare(arr, s1, s2)){
c += e1 - s1 + 1;
s2 += 1;
}
else {
s1 += 1;
}
}
else if (g == 0){
if (compare(arr, s1, s2)){
c += e2 - s2 + 1;
s1 += 1;
}
else {
s2 += 1;
}
}
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;
vector< int > aux;
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;
}
}
while (s1 <= e1){
aux.push_back(arr[s1]);
s1 += 1;
}
while (s2 <= e2){
aux.push_back(arr[s2]);
s2 += 1;
}
for ( int i = s; i <= e; i++){
arr[i] = aux[i-s];
}
return c;
}
int findElementsOnRight( int arr[], int s,
int e, int g){
if (s >= e){
return 0;
}
int mid = (s+e)/2;
int c1 = findElementsOnRight(
arr, s, mid, g);
int c2 = findElementsOnRight(
arr, mid + 1, e, g);
int c3 = findIntraArrayCount(
arr, s, mid, mid+1, e, g);
return c1 + c2 + c3;
}
int main()
{
int arr[] = {4, 3, 2, 1};
int g = 1;
cout << findElementsOnRight(arr, 0, 3, g);
return 0;
}
|
Java
import java.io.*;
import java.lang.*;
import java.util.*;
class GFG {
public static boolean compare(
int [] arr, int s1, int s2){
if (arr[s1] > arr[s2]){
return true ;
}
else {
return false ;
}
}
public static int findIntraArrayCount(
int [] arr, int s1, int e1, int s2,
int e2, int g){
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;
}
int c = 0 ;
int s = s1, e = e2, s3 = s1;
int e3 = e1, s4 = s2, e4 = e2;
while (s1 <= e1 && s2 <= e2){
if (g == 1 ){
if (compare(arr, s1, s2)){
c += e1 - s1 + 1 ;
s2 += 1 ;
}
else {
s1 += 1 ;
}
}
else if (g == 0 ){
if (compare(arr, s1, s2)){
c += e2 - s2 + 1 ;
s1 += 1 ;
}
else {
s2 += 1 ;
}
}
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;
ArrayList<Integer> aux =
new ArrayList<>();
while (s1 <= e1 && s2 <= e2){
if (arr[s1] <= arr[s2]){
aux.add(arr[s1]);
s1 += 1 ;
}
else {
aux.add(arr[s2]);
s2 += 1 ;
}
}
while (s1 <= e1){
aux.add(arr[s1]);
s1 += 1 ;
}
while (s2 <= e2){
aux.add(arr[s2]);
s2 += 1 ;
}
for ( int i = s; i <= e; i++){
arr[i] = aux.get(i-s);
}
return c;
}
public static int findElementsOnRight(
int [] arr, int s, int e, int g){
if (s >= e){
return 0 ;
}
int mid = (s+e)/ 2 ;
int c1 = findElementsOnRight(arr, s,
mid, g);
int c2 = findElementsOnRight(arr, mid + 1 ,
e, g);
int c3 = findIntraArrayCount(arr, s,
mid, mid+ 1 , e, g);
return c1 + c2 + c3;
}
public static void main (String[] args) {
int [] arr = { 4 , 3 , 2 , 1 };
int g = 1 ;
System.out.println(
findElementsOnRight(arr, 0 , 3 , g));
}
}
|
Python3
import random, math
from copy import deepcopy as dc
def compare(arr, s1, s2):
if arr[s1] > arr[s2]:
return True
else :
return False
def findIntraArrayCount(arr, s1, \
e1, s2, e2, g):
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 c
c = 0
s = dc(s1); e = dc(e2)
s3 = dc(s1); e3 = dc(e1)
s4 = dc(s2); e4 = dc(e2)
while s1 < = e1 and s2 < = e2:
if g = = 1 :
if compare(arr, s1, s2):
c + = e1 - s1 + 1
s2 + = 1
else :
s1 + = 1
elif g = = 0 :
if compare(arr, s1, s2):
c + = e2 - s2 + 1
s1 + = 1
else :
s2 + = 1
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)
aux = []
while s1 < = e1 and s2 < = e2:
if arr[s1] < = arr[s2]:
aux.append(arr[s1])
s1 + = 1
else :
aux.append(arr[s2])
s2 + = 1
while s1 < = e1:
aux.append(arr[s1])
s1 + = 1
while s2 < = e2:
aux.append(arr[s2])
s2 + = 1
for i in range (s, e + 1 ):
arr[i] = aux[i - s]
return c
def findElementsOnRight(arr, s, e, g):
if s > = e:
return 0
mid = (s + e) / / 2
c1 = findElementsOnRight(arr, s, \
mid, g)
c2 = findElementsOnRight(arr, mid + 1 , \
e, g)
c3 = findIntraArrayCount(arr, s, mid, \
mid + 1 , e, g)
return c1 + c2 + c3
if __name__ = = "__main__" :
arr = [ 4 , 3 , 2 , 1 ]
g = 1
out = findElementsOnRight(arr, 0 , \
len (arr) - 1 , g)
print (out)
|
C#
using System;
using System.Collections.Generic;
class GFG{
public static bool compare( int [] arr, int s1,
int s2)
{
if (arr[s1] > arr[s2])
{
return true ;
}
else
{
return false ;
}
}
public static int findIntraArrayCount( int [] arr, int s1,
int e1, int s2,
int e2, int g)
{
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;
}
int c = 0;
int s = s1, e = e2, s3 = s1;
int e3 = e1, s4 = s2, e4 = e2;
while (s1 <= e1 && s2 <= e2)
{
if (g == 1)
{
if (compare(arr, s1, s2))
{
c += e1 - s1 + 1;
s2 += 1;
}
else
{
s1 += 1;
}
}
else if (g == 0)
{
if (compare(arr, s1, s2))
{
c += e2 - s2 + 1;
s1 += 1;
}
else
{
s2 += 1;
}
}
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;
List< int > aux = new List< int >();
while (s1 <= e1 && s2 <= e2)
{
if (arr[s1] <= arr[s2])
{
aux.Add(arr[s1]);
s1 += 1;
}
else
{
aux.Add(arr[s2]);
s2 += 1;
}
}
while (s1 <= e1)
{
aux.Add(arr[s1]);
s1 += 1;
}
while (s2 <= e2)
{
aux.Add(arr[s2]);
s2 += 1;
}
for ( int i = s; i <= e; i++)
{
arr[i] = aux[i-s];
}
return c;
}
public static int findElementsOnRight( int [] arr, int s,
int e, int g)
{
if (s >= e)
{
return 0;
}
int mid = (s + e) / 2;
int c1 = findElementsOnRight(arr, s,
mid, g);
int c2 = findElementsOnRight(arr, mid + 1,
e, g);
int c3 = findIntraArrayCount(arr, s, mid,
mid + 1, e, g);
return c1 + c2 + c3;
}
static public void Main()
{
int [] arr = { 4, 3, 2, 1 };
int g = 1;
Console.WriteLine(findElementsOnRight(
arr, 0, 3, g));
}
}
|
Javascript
<script>
function compare(arr, s1, s2) {
if (arr[s1] > arr[s2]) {
return true ;
}
else {
return false ;
}
}
function findIntraArrayCount(arr, s1, e1, s2, e2, g) {
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;
}
let c = 0;
let s = s1, e = e2, s3 = s1;
let e3 = e1, s4 = s2, e4 = e2;
while (s1 <= e1 && s2 <= e2) {
if (g == 1) {
if (compare(arr, s1, s2)) {
c += e1 - s1 + 1;
s2 += 1;
}
else {
s1 += 1;
}
}
else if (g == 0) {
if (compare(arr, s1, s2)) {
c += e2 - s2 + 1;
s1 += 1;
}
else {
s2 += 1;
}
}
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;
let aux = new Array();
while (s1 <= e1 && s2 <= e2) {
if (arr[s1] <= arr[s2]) {
aux.push(arr[s1]);
s1 += 1;
}
else {
aux.push(arr[s2]);
s2 += 1;
}
}
while (s1 <= e1) {
aux.push(arr[s1]);
s1 += 1;
}
while (s2 <= e2) {
aux.push(arr[s2]);
s2 += 1;
}
for (let i = s; i <= e; i++) {
arr[i] = aux[i - s];
}
return c;
}
function findElementsOnRight(arr, s, e, g) {
if (s >= e) {
return 0;
}
let mid = Math.floor((s + e) / 2);
let c1 = findElementsOnRight(
arr, s, mid, g);
let c2 = findElementsOnRight(
arr, mid + 1, e, g);
let c3 = findIntraArrayCount(
arr, s, mid, mid + 1, e, g);
return c1 + c2 + c3;
}
let arr = [4, 3, 2, 1];
let g = 1;
document.write(findElementsOnRight(arr, 0, 3, g));
</script>
|
Time Complexity: The above method takes O(N*logN) time.
Auxiliary Space: O(N)
Last Updated :
19 Sep, 2023
Like Article
Save Article
Share your thoughts in the comments
Please Login to comment...