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++
#include <bits/stdc++.h>
using namespace std;
int countReversePairs( int arr[], int n)
{
int cnt = 0;
for ( int i = 0; i < n; i++) {
for ( int j = i + 1; j < n; j++) {
if (arr[i] > 2 * arr[j]) {
cnt++;
}
}
}
return cnt;
}
int main()
{
int arr[] = { 3, 2, 4, 5, 1, 20 };
int n = sizeof (arr) / sizeof (arr[0]);
cout << "Reverse pairs are: "
<< countReversePairs(arr, n) << endl;
return 0;
}
|
Java
public class ReversePairsCount {
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++) {
if (arr[i] > 2 * arr[j]) {
cnt++;
}
}
}
return cnt;
}
public static void main(String[] args) {
int [] arr = { 3 , 2 , 4 , 5 , 1 , 20 };
System.out.println( "Reverse pairs are: " + countReversePairs(arr));
}
}
|
Python3
def countReversePairs(arr, n):
cnt = 0
for i in range ( 0 , n):
for j in range (i + 1 , n):
if arr[i] > 2 * arr[j]:
cnt + = 1
return cnt
arr = [ 3 , 2 , 4 , 5 , 1 , 20 ]
n = len (arr)
print ( "Reverse pairs are:" , countReversePairs(arr, n))
|
C#
using System;
class Program
{
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++)
{
if (arr[i] > 2 * arr[j])
{
cnt++;
}
}
}
return cnt;
}
static void Main( string [] args)
{
int [] arr = { 3, 2, 4, 5, 1, 20 };
Console.WriteLine( "Reverse pairs are: " + CountReversePairs(arr));
}
}
|
Javascript
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++) {
if (arr[i] > 2 * arr[j]) {
cnt++;
}
}
}
return cnt;
}
const arr = [3, 2, 4, 5, 1, 20];
console.log( "Reverse pairs are: " + countReversePairs(arr));
|
Output
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++
#include <iostream>
using namespace std;
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++];
}
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++];
}
}
while (i < len1) {
arr[k++] = first[i++];
}
while (j < len2) {
arr[k++] = second[j++];
}
}
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;
}
cnt += mergeSort(arr, low, mid);
cnt += mergeSort(arr, mid + 1, high);
cnt += countReversePairs(arr, low, mid, high);
merge(arr, low, mid, high);
return cnt;
}
int main()
{
int arr[] = { 3, 2, 4, 5, 1, 20 };
int n = sizeof (arr) / sizeof (arr[0]);
cout << "Reverse pairs are: "
<< mergeSort(arr, 0, n - 1) << endl;
return 0;
}
|
Java
public class ReversePairsCount {
static 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++];
}
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++];
}
}
while (i < len1) {
arr[k++] = first[i++];
}
while (j < len2) {
arr[k++] = second[j++];
}
}
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;
}
static int mergeSort( int [] arr, int low, int high) {
int cnt = 0 ;
if (low >= high) {
return cnt;
}
int mid = low + (high - low) / 2 ;
cnt += mergeSort(arr, low, mid);
cnt += mergeSort(arr, mid + 1 , high);
cnt += countReversePairs(arr, low, mid, high);
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;
System.out.println( "Reverse pairs are: " + mergeSort(arr, 0 , n - 1 ));
}
}
|
Python3
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
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
while i < len1:
arr[k] = first[i];
k + = 1
i + = 1
while j < len2:
arr[k] = second[j]
j + = 1
k + = 1
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
cnt + = mergeSort(arr, low, mid)
cnt + = mergeSort(arr, mid + 1 , high)
cnt + = countReversePairs(arr, low, mid, high)
merge(arr, low, mid, high)
return cnt
arr = [ 3 , 2 , 4 , 5 , 1 , 20 ]
n = len (arr)
print ( "Reverse pairs are:" , mergeSort(arr, 0 , n - 1 ))
|
C#
using System;
class Program {
static 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++];
}
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++];
}
}
while (i < len1) {
arr[k++] = first[i++];
}
while (j < len2) {
arr[k++] = second[j++];
}
}
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;
}
static int MergeSort( int [] arr, int low, int high) {
int cnt = 0;
if (low >= high) {
return cnt;
}
int mid = low + (high - low) / 2;
cnt += MergeSort(arr, low, mid);
cnt += MergeSort(arr, mid + 1, high);
cnt += CountReversePairs(arr, low, mid, high);
Merge(arr, low, mid, high);
return cnt;
}
static void Main( string [] args) {
int [] arr = { 3, 2, 4, 5, 1, 20 };
int n = arr.Length;
Console.WriteLine( "Reverse pairs are: " + MergeSort(arr, 0, n - 1));
}
}
|
Javascript
function merge(arr, low, mid, high) {
const len1 = mid - low + 1;
const len2 = high - mid;
const first = new Array(len1);
const second = new Array(len2);
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++];
}
let 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++];
}
}
while (i < len1) {
arr[k++] = first[i++];
}
while (j < len2) {
arr[k++] = second[j++];
}
}
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;
}
function mergeSort(arr, low, high) {
let cnt = 0;
if (low >= high) {
return cnt;
}
const mid = low + Math.floor((high - low) / 2);
cnt += mergeSort(arr, low, mid);
cnt += mergeSort(arr, mid + 1, high);
cnt += countReversePairs(arr, low, mid, high);
merge(arr, low, mid, high);
return cnt;
}
const arr = [3, 2, 4, 5, 1, 20];
console.log( "Reverse pairs are: " + mergeSort(arr, 0, arr.length - 1));
|
Output
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.
|