Given an array arr[] of N integers, find the count of reverse pairs. A pair of indices (i, j) is said to be a reverse pair if both the following conditions are met:
-
0 <= i < j < N
arr[i] > 2 * arr[j]
Examples:
Input: N = 6, arr = [3, 2, 4, 5, 1, 20]
Output: 3
Explanation: The reverse pairs are:
- (0, 4), arr[0] = 3 and arr[4] = 1, 3 > 2(1)
- (2, 4), arr[2] = 4 and arr[4] = 1, 4 > 2(1)
- (3, 4), arr[3] = 5 and arr[4] = 1, 5 > 2(1)
Input: N = 5, arr = [2, 4, 3, 5, 1]
Output: 3
Explanation: The reverse pairs are:
- (1, 4), arr[1] = 4 and arr[4] = 1, 4 > 2(1)
- (2, 4), arr[2] = 3 and arr[4] = 1, 3 > 2(1)
- (3, 4), arr[3] = 5 and arr[4] = 1, 5 > 2(1)
Naïve Approach: To solve the problem follow the below steps:
- Run the outer loop(say i) from 0 to N-1.
- As the index j should be greater than I, so run the inner loop(say j) from i+1 to N-1.
- If the condition arr[i] > 2*arr[j] is satisfied, then increment the cnt.
- Return the cnt i.e. the count of reverse pairs.
Below is the implementation of the above approach:
// C++ program to count the reverse pairs #include <bits/stdc++.h> using namespace std;
// function to count the reverse pairs int countReversePairs( int arr[], int n)
{ int cnt = 0;
for ( int i = 0; i < n; i++) {
for ( int j = i + 1; j < n; j++) {
// Condition for reverse pairs
if (arr[i] > 2 * arr[j]) {
cnt++;
}
}
}
return cnt;
} // Drivers code int main()
{ int arr[] = { 3, 2, 4, 5, 1, 20 };
int n = sizeof (arr) / sizeof (arr[0]);
// Function Call
cout << "Reverse pairs are: "
<< countReversePairs(arr, n) << endl;
return 0;
} |
public class ReversePairsCount {
// Function to count the reverse pairs
static int countReversePairs( int [] arr) {
int cnt = 0 ;
int n = arr.length;
for ( int i = 0 ; i < n; i++) {
for ( int j = i + 1 ; j < n; j++) {
// Condition for reverse pairs
if (arr[i] > 2 * arr[j]) {
cnt++;
}
}
}
return cnt;
}
public static void main(String[] args) {
int [] arr = { 3 , 2 , 4 , 5 , 1 , 20 };
// Function Call
System.out.println( "Reverse pairs are: " + countReversePairs(arr));
}
} |
# Python program for the above approach: # function to count the reverse pairs def countReversePairs(arr, n):
cnt = 0
for i in range ( 0 , n):
for j in range (i + 1 , n):
# Condition for reverse pairs
if arr[i] > 2 * arr[j]:
cnt + = 1
return cnt
# Drivers code arr = [ 3 , 2 , 4 , 5 , 1 , 20 ]
n = len (arr)
# Function Call print ( "Reverse pairs are:" , countReversePairs(arr, n))
|
using System;
class Program
{ // Function to count the reverse pairs
static int CountReversePairs( int [] arr)
{
int cnt = 0;
int n = arr.Length;
for ( int i = 0; i < n; i++)
{
for ( int j = i + 1; j < n; j++)
{
// Condition for reverse pairs
if (arr[i] > 2 * arr[j])
{
cnt++;
}
}
}
return cnt;
}
static void Main( string [] args)
{
int [] arr = { 3, 2, 4, 5, 1, 20 };
// Function Call
Console.WriteLine( "Reverse pairs are: " + CountReversePairs(arr));
}
} |
// Function to count the reverse pairs function countReversePairs(arr) {
let cnt = 0;
const n = arr.length;
for (let i = 0; i < n; i++) {
for (let j = i + 1; j < n; j++) {
// Condition for reverse pairs
if (arr[i] > 2 * arr[j]) {
cnt++;
}
}
}
return cnt;
} const arr = [3, 2, 4, 5, 1, 20]; // Function Call console.log( "Reverse pairs are: " + countReversePairs(arr));
|
Reverse pairs are: 3
Time Complexity: O(N2), two nested loops are used up to N.
Auxiliary Space: O(1), no extra space is used.
Efficient Approach: To solve the problem follow the below idea:
The approach is the same as the merge sort algorithm but the minor difference is that we add an additional function to count the reverse pairs.
The countReversePairs() function will work as follows:
- Initialize the cnt variable with zero.
- Run a loop(say i) from low to mid i.e. for the left half.
- Run another loop(say j) for the right half which starts from the mid+1 and ends at high.
- If arr[i] > 2* arr[j], then increment the cnt variable.
- Else, increment the cnt by j-(mid+1).
- Either if i reaches mid or j reaches end(>=high) return the cnt.
The changes in the mergeSort() function are as follows:
- Initialize the cnt variable with zero.
- Add the count of reverse pairs in the cnt variable return by the previous mergeSort() function.
- Before calling the merge() function count the number of reverse pairs.
- If the low becomes greater than equal to the high, return the cnt (the left half starts from the low and ends at mid and the right half starts from mid+1 and ends at high).
Below is the implementation of the above approach:
// C++ program to count the reverse pairs #include <iostream> using namespace std;
// Merge function void merge( int arr[], int low, int mid, int high)
{ int len1 = mid - low + 1;
int len2 = high - mid;
int * first = new int [len1];
int * second = new int [len2];
int k = low;
for ( int i = 0; i < len1; i++) {
first[i] = arr[k++];
}
k = mid + 1;
for ( int i = 0; i < len2; i++) {
second[i] = arr[k++];
}
// Storing the elements in the arr
// in sorted manner
int i = 0, j = 0;
k = low;
while (i < len1 && j < len2) {
if (first[i] <= second[j]) {
arr[k++] = first[i++];
}
else {
arr[k++] = second[j++];
}
}
// Storing the left out elements
// of first half
while (i < len1) {
arr[k++] = first[i++];
}
// Storing the left out elements
// of right half
while (j < len2) {
arr[k++] = second[j++];
}
} // Function to count the reverse pairs int countReversePairs( int arr[], int low, int mid, int high)
{ int cnt = 0;
int j = mid + 1;
for ( int i = low; i <= mid; i++) {
while (i <= high && arr[i] > 2 * arr[j]) {
j++;
}
cnt += (j - (mid + 1));
}
return cnt;
} int mergeSort( int arr[], int low, int high)
{ int cnt = 0;
int mid = low + (high - low) / 2;
if (low >= high) {
return cnt;
}
// Count the left half pairs
cnt += mergeSort(arr, low, mid);
// Count the right half pairs
cnt += mergeSort(arr, mid + 1, high);
// Function call to count the reverse pairs
cnt += countReversePairs(arr, low, mid, high);
// Merging the first and second half
merge(arr, low, mid, high);
return cnt;
} // Drivers code int main()
{ int arr[] = { 3, 2, 4, 5, 1, 20 };
int n = sizeof (arr) / sizeof (arr[0]);
// Function Call
cout << "Reverse pairs are: "
<< mergeSort(arr, 0, n - 1) << endl;
return 0;
} |
public class ReversePairsCount {
// Merge function to merge two sorted subarrays
static void merge( int [] arr, int low, int mid, int high) {
// Calculate the lengths of the two subarrays
int len1 = mid - low + 1 ;
int len2 = high - mid;
// Create temporary arrays to hold the subarrays
int [] first = new int [len1];
int [] second = new int [len2];
// Copy data from the main array to the temporary arrays
int k = low;
for ( int i = 0 ; i < len1; i++) {
first[i] = arr[k++];
}
k = mid + 1 ;
for ( int i = 0 ; i < len2; i++) {
second[i] = arr[k++];
}
// Merge the two subarrays back into the main array
int i = 0 , j = 0 ;
k = low;
while (i < len1 && j < len2) {
// Compare and merge elements in sorted order
if (first[i] <= second[j]) {
arr[k++] = first[i++];
} else {
arr[k++] = second[j++];
}
}
// Copy any remaining elements from the temporary arrays
while (i < len1) {
arr[k++] = first[i++];
}
while (j < len2) {
arr[k++] = second[j++];
}
}
// Function to count the reverse pairs using merge sort
static int countReversePairs( int [] arr, int low, int mid, int high) {
int cnt = 0 ;
int j = mid + 1 ;
for ( int i = low; i <= mid; i++) {
while (i <= high && arr[i] > 2 * arr[j]) {
j++;
}
cnt += (j - (mid + 1 ));
}
return cnt;
}
// Merge Sort function to sort the array and count reverse pairs
static int mergeSort( int [] arr, int low, int high) {
int cnt = 0 ;
if (low >= high) {
return cnt;
}
int mid = low + (high - low) / 2 ;
// Recursively count reverse pairs in left and right halves
cnt += mergeSort(arr, low, mid);
cnt += mergeSort(arr, mid + 1 , high);
// Merge the sorted halves and count reverse pairs
cnt += countReversePairs(arr, low, mid, high);
// Merge the two halves
merge(arr, low, mid, high);
return cnt;
}
public static void main(String[] args) {
int [] arr = { 3 , 2 , 4 , 5 , 1 , 20 };
int n = arr.length;
// Function Call to count reverse pairs
System.out.println( "Reverse pairs are: " + mergeSort(arr, 0 , n - 1 ));
}
} |
# Python program for the above approach: # Merge function def merge(arr, low, mid, high):
len1 = mid - low + 1 ;
len2 = high - mid;
first = [ 0 ] * len1;
second = [ 0 ] * len2;
k = low
for i in range ( 0 , len1):
first[i] = arr[k]
k + = 1
k = mid + 1 ;
for i in range ( 0 , len2):
second[i] = arr[k]
k + = 1
# Storing the elements in the arr
# in sorted manner
i = 0
j = 0
k = low
while i < len1 and j < len2:
if first[i] < = second[j]:
arr[k] = first[i]
k + = 1
i + = 1
else :
arr[k] = second[j];
k + = 1
j + = 1
# Storing the left out elements
# of first half
while i < len1:
arr[k] = first[i];
k + = 1
i + = 1
# Storing the left out elements
# of right half
while j < len2:
arr[k] = second[j]
j + = 1
k + = 1
# Function to count the reverse pairs def countReversePairs(arr, low, mid, high):
cnt = 0
j = mid + 1
for i in range (low, mid + 1 ):
while i < = high and arr[i] > 2 * arr[j]:
j + = 1
cnt + = (j - (mid + 1 ))
return cnt
def mergeSort(arr, low, high):
cnt = 0 ;
mid = low + (high - low) / / 2 ;
if low > = high:
return cnt
# Count the left half pairs
cnt + = mergeSort(arr, low, mid)
# Count the right half pairs
cnt + = mergeSort(arr, mid + 1 , high)
# Function call to count the reverse pairs
cnt + = countReversePairs(arr, low, mid, high)
# Merging the first and second half
merge(arr, low, mid, high)
return cnt
# Drivers code arr = [ 3 , 2 , 4 , 5 , 1 , 20 ]
n = len (arr)
# Function Call print ( "Reverse pairs are:" , mergeSort(arr, 0 , n - 1 ))
|
using System;
class Program {
// Merge function to merge two sorted subarrays
static void Merge( int [] arr, int low, int mid, int high) {
// Calculate the lengths of the two subarrays
int len1 = mid - low + 1;
int len2 = high - mid;
// Create temporary arrays to hold the subarrays
int [] first = new int [len1];
int [] second = new int [len2];
// Copy data from the main array to the temporary arrays
int k = low;
for ( int i = 0; i < len1; i++) {
first[i] = arr[k++];
}
k = mid + 1;
for ( int i = 0; i < len2; i++) {
second[i] = arr[k++];
}
// Merge the two subarrays back into the main array
int i = 0, j = 0;
k = low;
while (i < len1 && j < len2) {
// Compare and merge elements in sorted order
if (first[i] <= second[j]) {
arr[k++] = first[i++];
} else {
arr[k++] = second[j++];
}
}
// Copy any remaining elements from the temporary arrays
while (i < len1) {
arr[k++] = first[i++];
}
while (j < len2) {
arr[k++] = second[j++];
}
}
// Function to count the reverse pairs using merge sort
static int CountReversePairs( int [] arr, int low, int mid, int high) {
int cnt = 0;
int j = mid + 1;
for ( int i = low; i <= mid; i++) {
while (i <= high && arr[i] > 2 * arr[j]) {
j++;
}
cnt += (j - (mid + 1));
}
return cnt;
}
// Merge Sort function to sort the array and count reverse pairs
static int MergeSort( int [] arr, int low, int high) {
int cnt = 0;
if (low >= high) {
return cnt;
}
int mid = low + (high - low) / 2;
// Recursively count reverse pairs in left and right halves
cnt += MergeSort(arr, low, mid);
cnt += MergeSort(arr, mid + 1, high);
// Merge the sorted halves and count reverse pairs
cnt += CountReversePairs(arr, low, mid, high);
// Merge the two halves
Merge(arr, low, mid, high);
return cnt;
}
static void Main( string [] args) {
int [] arr = { 3, 2, 4, 5, 1, 20 };
int n = arr.Length;
// Function Call to count reverse pairs
Console.WriteLine( "Reverse pairs are: " + MergeSort(arr, 0, n - 1));
}
} |
// Merge function to merge two sorted subarrays function merge(arr, low, mid, high) {
// Calculate the lengths of the two subarrays
const len1 = mid - low + 1;
const len2 = high - mid;
// Create arrays to hold the subarrays
const first = new Array(len1);
const second = new Array(len2);
// Copy data from the main array to the temporary arrays
let k = low;
for (let i = 0; i < len1; i++) {
first[i] = arr[k++];
}
k = mid + 1;
for (let i = 0; i < len2; i++) {
second[i] = arr[k++];
}
// Merge the two subarrays back into the main array
let i = 0, j = 0;
k = low;
while (i < len1 && j < len2) {
// Compare and merge elements in sorted order
if (first[i] <= second[j]) {
arr[k++] = first[i++];
} else {
arr[k++] = second[j++];
}
}
// Copy any remaining elements from the temporary arrays
while (i < len1) {
arr[k++] = first[i++];
}
while (j < len2) {
arr[k++] = second[j++];
}
} // Function to count the reverse pairs using merge sort function countReversePairs(arr, low, mid, high) {
let cnt = 0;
let j = mid + 1;
for (let i = low; i <= mid; i++) {
while (i <= high && arr[i] > 2 * arr[j]) {
j++;
}
cnt += (j - (mid + 1));
}
return cnt;
} // Merge Sort function to sort the array and count reverse pairs function mergeSort(arr, low, high) {
let cnt = 0;
if (low >= high) {
return cnt;
}
const mid = low + Math.floor((high - low) / 2);
// Recursively count reverse pairs in left and right halves
cnt += mergeSort(arr, low, mid);
cnt += mergeSort(arr, mid + 1, high);
// Merge the sorted halves and count reverse pairs
cnt += countReversePairs(arr, low, mid, high);
// Merge the two halves
merge(arr, low, mid, high);
return cnt;
} const arr = [3, 2, 4, 5, 1, 20]; // Function Call to count reverse pairs console.log( "Reverse pairs are: " + mergeSort(arr, 0, arr.length - 1));
|
Reverse pairs are: 3
Complexity Analysis:
- Time Complexity: O(N*log(N)), the time complexity of the mergeSort() function is O(N*logN) and the countReversePairs() function and merge() function is called inside the mergeSort() function whose time complexity is O(N) for each function. So, the overall time complexity of the function is O(logN)*O(N).
- Auxiliary Space: O(N), as the extra array is used to store the elements.