Given an array arr[] of n positive integers, count the number of good pairs (i , j ) such that:
- 1 ≤ i, j ≤ array size
- arr[i] < arr[j]
Two pairs are considered different if they differ in at least one index. Since the answer can be very large, return it modulo 10 ^ 9+7.
1 ≤ n ≤ 10^5
1 ≤ arr[i] ≤ 10^3
Examples :
Input: arr[] = [2, 1]
Output: 1
Explanation: The only good pair is (2,1).Input: arr[] = [2 ,3, 2]
Output: 2
Explanation: The two good pairs are (2,3) and (3,2).
Table of Content
[Naive Approach] Check Every Ordered Pair - O(n ^ 2) Time and O(1) Space
The idea is to check every ordered pair (i, j) in the array. If arr[i] < arr[j], then it is a good pair. Count all such pairs and return the answer modulo 10^9 + 7.
Working of Approach:
- Traverse every ordered pair (i, j).
- Skip the pair if i == j.
- If arr[i] < arr[j], increment the answer.
- Return the answer modulo 10^9 + 7.
#include <iostream>
#include <vector>
using namespace std;
int solve(vector<int> &arr)
{
const int MOD = 1000000007;
long long res = 0;
int n = arr.size();
// Check every ordered pair
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
// Count good pairs
if (i != j && arr[i] < arr[j])
res++;
}
}
return res % MOD;
}
int main()
{
vector<int> arr = {2, 3, 2};
cout << solve(arr);
return 0;
}
import java.util.Arrays;
public class GFG {
static int solve(int[] arr)
{
final int MOD = 1000000007;
long res = 0;
int n = arr.length;
// Check every ordered pair
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
// Count good pairs
if (i != j && arr[i] < arr[j])
res++;
}
}
return (int)(res % MOD);
}
public static void main(String[] args)
{
int[] arr = { 2, 3, 2 };
System.out.println(solve(arr));
}
}
def solve(arr):
MOD = 1000000007
res = 0
n = len(arr)
# Check every ordered pair
for i in range(n):
for j in range(n):
# Count good pairs
if i != j and arr[i] < arr[j]:
res += 1
return res % MOD
if __name__ == "__main__":
arr = [2, 3, 2]
print(solve(arr))
using System;
class GFG {
static int solve(int[] arr)
{
const int MOD = 1000000007;
long res = 0;
int n = arr.Length;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (i != j && arr[i] < arr[j])
res++;
}
}
return (int)(res % MOD);
}
static void Main()
{
int[] arr = { 2, 3, 2 };
Console.WriteLine(solve(arr));
}
}
function solve(arr)
{
const MOD = 1000000007;
let res = 0;
const n = arr.length;
// Check every ordered pair
for (let i = 0; i < n; i++) {
for (let j = 0; j < n; j++) {
// Count good pairs
if (i !== j && arr[i] < arr[j])
res++;
}
}
return res % MOD;
}
// Driver Code
const arr = [ 2, 3, 2 ];
console.log(solve(arr));
Output
2
[Better Approach] Sort the Array and Use Binary Search - O(n log n) Time and O(1) Space
The idea is to sort the array. For every distinct value, use binary search to find the first element that is strictly greater than it. Since the array is sorted, all elements after that position are greater. Every occurrence of the current value forms a good pair with each of those greater elements.
Working of Approach:
- Sort the array.
- Traverse the sorted array by groups of equal elements.
- Let the current value occur freq times.
- Use upper_bound() to find the first element greater than the current value.
- Let greaterCnt be the number of elements after that position.
- Add freq × greaterCnt to the answer.
- Skip all duplicate occurrences and continue.
#include <iostream>
#include <vector>
using namespace std;
int solve(vector<int> &arr)
{
const int MOD = 1000000007;
// Sort the array
sort(arr.begin(), arr.end());
long long res = 0;
int n = arr.size();
int i = 0;
while (i < n)
{
// Count the frequency of the current value
int j = i;
while (j < n && arr[j] == arr[i])
j++;
int freq = j - i;
// Find the first element greater than the current value
auto it = upper_bound(arr.begin(), arr.end(), arr[i]);
// Count the number of greater elements
long long greaterCnt = arr.end() - it;
// Add the contribution of the current value
res = (res + 1LL * freq * greaterCnt) % MOD;
// Move to the next distinct value
i = j;
}
return res;
}
int main()
{
vector<int> arr = {2, 3, 2};
cout << solve(arr);
return 0;
}
import java.util.Arrays;
public class GFG {
static final int MOD = 1000000007;
public static int solve(int[] arr)
{
// Sort the array
Arrays.sort(arr);
long res = 0;
int n = arr.length;
int i = 0;
while (i < n) {
// Count the frequency of the current value
int j = i;
while (j < n && arr[j] == arr[i])
j++;
int freq = j - i;
// Find the first element greater than the
// current value
int it = upperBound(arr, arr[i]);
// Count the number of greater elements
long greaterCnt = n - it;
// Add the contribution of the current value
res = (res + 1L * freq * greaterCnt) % MOD;
// Move to the next distinct value
i = j;
}
return (int)res;
}
private static int upperBound(int[] arr, int target)
{
int left = 0;
int right = arr.length;
while (left < right) {
int mid = left + (right - left) / 2;
if (arr[mid] > target)
right = mid;
else
left = mid + 1;
}
return left;
}
public static void main(String[] args)
{
int[] arr = { 2, 3, 2 };
System.out.println(solve(arr));
}
}
from bisect import bisect_right
def solve(arr):
MOD = 1000000007
# Sort the array
arr.sort()
res = 0
n = len(arr)
i = 0
while i < n:
# Count the frequency of the current value
j = i
while j < n and arr[j] == arr[i]:
j += 1
freq = j - i
# Find the first element greater than the current value
it = bisect_right(arr, arr[i])
# Count the number of greater elements
greaterCnt = len(arr) - it
# Add the contribution of the current value
res = (res + freq * greaterCnt) % MOD
# Move to the next distinct value
i = j
return res
if __name__ == '__main__':
arr = [2, 3, 2]
print(solve(arr))
using System;
class GFG {
static int UpperBound(int[] arr, int target)
{
int low = 0, high = arr.Length;
while (low < high) {
int mid = low + (high - low) / 2;
if (arr[mid] <= target)
low = mid + 1;
else
high = mid;
}
return low;
}
static int solve(int[] arr)
{
const int MOD = 1000000007;
// Sort the array
Array.Sort(arr);
long res = 0;
int n = arr.Length;
int i = 0;
while (i < n) {
// Count the frequency of the current value
int j = i;
while (j < n && arr[j] == arr[i])
j++;
int freq = j - i;
// Find the first element greater than the
// current value
int idx = UpperBound(arr, arr[i]);
// Count the number of greater elements
long greaterCnt = n - idx;
// Add the contribution of the current value
res = (res + 1L * freq * greaterCnt) % MOD;
// Move to the next distinct value
i = j;
}
return (int)res;
}
static void Main()
{
int[] arr = { 2, 3, 2 };
Console.WriteLine(solve(arr));
}
}
function upperBound(arr, target)
{
let low = 0;
let high = arr.length;
while (low < high) {
let mid = Math.floor((low + high) / 2);
if (arr[mid] <= target)
low = mid + 1;
else
high = mid;
}
return low;
}
function solve(arr)
{
const MOD = 1000000007;
// Sort the array
arr.sort((a, b) => a - b);
let res = 0;
let n = arr.length;
let i = 0;
while (i < n) {
// Count the frequency of the current value
let j = i;
while (j < n && arr[j] === arr[i])
j++;
let freq = j - i;
// Find the first element greater than the current
// value
let idx = upperBound(arr, arr[i]);
// Count the number of greater elements
let greaterCnt = n - idx;
// Add the contribution of the current value
res = (res + (freq * greaterCnt) % MOD) % MOD;
// Move to the next distinct value
i = j;
}
return res;
}
// Driver Code
let arr = [ 2, 3, 2 ];
console.log(solve(arr));
Output
2
[Expected Approach] Frequency Count and Suffix Greater Array - O(n + MAX) Time and O(MAX) Space
The idea based on the fact that the given array has a limited maximum value. We count frequency of every value and build a suffix array that stores how many elements are greater than each value. Then, for every array element, directly add the number of greater elements to the answer.
Working of Approach:
- Count the frequency of every value in the array.
- Build a suffix array where greater[x] stores the count of elements greater than x.
- Traverse the array and add greater[arr[i]] to the answer.
- Return the answer modulo 10^9 + 7.
Let us understand with an example:
Input: arr[] = [2 ,3, 2]
- Frequency array becomes: freq[2] = 2, freq[3] = 1.
- Build the greater array: greater[2] = 1 (only one element, 3, is greater than 2), and greater[3] = 0.
- Traverse the array and add greater[arr[i]] for each element: 1 + 0 + 1.
- Total good pairs = 2.
Hence, the output is 2.
#include <iostream>
#include <vector>
using namespace std;
int solve(vector<int> &arr)
{
const int MOD = 1e9 + 7;
const int MAX_VAL = 1000;
vector<int> freq(MAX_VAL + 1, 0);
// Store the frequency of every value
for (int x : arr)
freq[x]++;
vector<int> greater(MAX_VAL + 2, 0);
// Build suffix array where greater[i] stores
// the number of elements greater than i
for (int i = MAX_VAL - 1; i >= 1; i--)
greater[i] = greater[i + 1] + freq[i + 1];
long long res = 0;
// Count good pairs for every array element
for (int x : arr)
res = (res + greater[x]) % MOD;
return res;
}
int main()
{
vector<int> arr = {2, 3, 2};
cout << solve(arr);
return 0;
}
import java.util.Arrays;
public class GFG {
static int solve(int[] arr)
{
final int MOD = 1000000007;
final int MAX_VAL = 1000;
int[] freq = new int[MAX_VAL + 1];
// Store the frequency of every value
for (int x : arr)
freq[x]++;
int[] greater = new int[MAX_VAL + 2];
// Build suffix array where greater[i] stores
// the number of elements greater than i
for (int i = MAX_VAL - 1; i >= 1; i--)
greater[i] = greater[i + 1] + freq[i + 1];
long res = 0;
// Count good pairs for every array element
for (int x : arr)
res = (res + greater[x]) % MOD;
return (int)res;
}
public static void main(String[] args)
{
int[] arr = { 2, 3, 2 };
System.out.println(solve(arr));
}
}
def solve(arr):
MOD = 10**9 + 7
MAX_VAL = 1000
freq = [0] * (MAX_VAL + 1)
# Store the frequency of every value
for x in arr:
freq[x] += 1
greater = [0] * (MAX_VAL + 2)
# Build suffix array where greater[i] stores
# the number of elements greater than i
for i in range(MAX_VAL - 1, 0, -1):
greater[i] = greater[i + 1] + freq[i + 1]
res = 0
# Count good pairs for every array element
for x in arr:
res = (res + greater[x]) % MOD
return int(res)
if __name__ == "__main__":
arr = [2, 3, 2]
print(solve(arr))
using System;
class GFG {
static int solve(int[] arr)
{
const int MOD = 1000000007;
const int MAX_VAL = 1000;
int[] freq = new int[MAX_VAL + 1];
foreach(int x in arr) freq[x]++;
int[] greater = new int[MAX_VAL + 2];
for (int i = MAX_VAL - 1; i >= 1; i--)
greater[i] = greater[i + 1] + freq[i + 1];
long res = 0;
foreach(int x in arr) res
= (res + greater[x]) % MOD;
return (int)res;
}
static void Main()
{
int[] arr = { 2, 3, 2 };
Console.WriteLine(solve(arr));
}
}
function solve(arr)
{
const MOD = 1e9 + 7;
const MAX_VAL = 1000;
let freq = Array(MAX_VAL + 1).fill(0);
// Store the frequency of every value
for (let x of arr)
freq[x]++;
let greater = Array(MAX_VAL + 2).fill(0);
// Build suffix array where greater[i] stores
// the number of elements greater than i
for (let i = MAX_VAL - 1; i >= 1; i--)
greater[i] = greater[i + 1] + freq[i + 1];
let res = 0;
// Count good pairs for every array element
for (let x of arr)
res = (res + greater[x]) % MOD;
return Math.floor(res);
}
// Driver Code
let arr = [ 2, 3, 2 ];
console.log(solve(arr));
Output
2