Given an even-sized array arr[] of length n. A dominant pair (i, j) is defined as:
- i belongs to the first half of the array, (0 <= i < n/2)
- j belongs to the second half of the array, (n/2 <= j < n)
- The value at index i is at least five times the value at index j, (arr[i] >= 5 * arr[j])
The task is to find the count of total number of dominant pairs in the array.
Examples:
Input: arr[] = [10, 2, 2, 1]
Output: 2
Explanation: First half: [10, 2], Second half: [2, 1]. So valid pairs are:
- {0, 2}: 10 >= 5 × 2
- {0, 3}: 10 >= 5 × 1
So, total dominant pairs = 2.
Input: arr[] = [10, 8, 2, 1, 1, 2]
Output: 5
Explanation: First half: [10, 8, 2], Second half: [1, 1, 2]. So valid pairs are:
- {0, 3}: 10 >= 5 × 1
- {0, 4}: 10 >= 5 × 1
- {0, 5}: 10 >= 5 × 2
- {1, 3}: 8 >= 5 × 1
- {1, 4}: 8 >= 5 × 1
So, total dominant pairs = 5.
Table of Content
[Brute-Force Approach] Using 2 Nested Loops - O(n²) Time and O(1) Space
The idea is to check all possible (i, j) pairs where i belongs to the first half and j belongs to the second half of the array.
The brute-force approach uses two nested loops to compare each element from the first half with every element from the second half, ensuring the dominance condition (arr[i] >=5 * arr[j]) holds.
// C++ Code to find number of dominant pairs
// in an array using 2 Nested Loops
#include <iostream>
#include <vector>
using namespace std;
int dominantPairs(vector<int> &arr) {
int n = arr.size();
int count = 0;
// Iterate through the first half of the array
for (int i = 0; i < n / 2; i++) {
// Iterate through the second half of
// the array
for (int j = n / 2; j < n; j++) {
// Check if arr[i] satisfies the
// dominance condition
if (arr[i] >= 5 * arr[j]) {
count++;
}
}
}
return count;
}
// Driver code
int main() {
vector<int> arr = {10, 2, 2, 1};
cout << dominantPairs(arr) << endl;
return 0;
}
// Java Code to find number of dominant pairs
// in an array using 2 Nested Loops
import java.util.*;
class GfG {
static int dominantPairs(int[] arr) {
int n = arr.length;
int count = 0;
// Iterate through the first half of the array
for (int i = 0; i < n / 2; i++) {
// Iterate through the second half of
// the array
for (int j = n / 2; j < n; j++) {
// Check if arr[i] satisfies the
// dominance condition
if (arr[i] >= 5 * arr[j]) {
count++;
}
}
}
return count;
}
// Driver code
public static void main(String[] args) {
int[] arr = {10, 2, 2, 1};
System.out.println(dominantPairs(arr));
}
}
# Python Code to find number of dominant pairs
# in an array using 2 Nested Loops
def dominantPairs(arr):
n = len(arr)
count = 0
# Iterate through the first half of the array
for i in range(n // 2):
# Iterate through the second half of
# the array
for j in range(n // 2, n):
# Check if arr[i] satisfies the
# dominance condition
if arr[i] >= 5 * arr[j]:
count += 1
return count
# Driver code
if __name__ == "__main__":
arr = [10, 2, 2, 1]
print(dominantPairs(arr))
// C# Code to find number of dominant pairs
// in an array using 2 Nested Loops
using System;
class GfG {
static int dominantPairs(int[] arr) {
int n = arr.Length;
int count = 0;
// Iterate through the first half of the array
for (int i = 0; i < n / 2; i++) {
// Iterate through the second half of
// the array
for (int j = n / 2; j < n; j++) {
// Check if arr[i] satisfies the
// dominance condition
if (arr[i] >= 5 * arr[j]) {
count++;
}
}
}
return count;
}
// Driver code
static void Main() {
int[] arr = {10, 2, 2, 1};
Console.WriteLine(dominantPairs(arr));
}
}
// JavaScript Code to find number of dominant pairs
// in an array using 2 Nested Loops
function dominantPairs(arr) {
let n = arr.length;
let count = 0;
// Iterate through the first half of the array
for (let i = 0; i < n / 2; i++) {
// Iterate through the second half of
// the array
for (let j = n / 2; j < n; j++) {
// Check if arr[i] satisfies the
// dominance condition
if (arr[i] >= 5 * arr[j]) {
count++;
}
}
}
return count;
}
// Driver code
let arr = [10, 2, 2, 1];
console.log(dominantPairs(arr));
Output
2
[Expected Approach] Using Sorting + Two Pointers - O(n*log(n)) Time and O(1) Space
We sort the first half and second half separately to maintain order.
We use two pointers to iterate through the two sorted halves . The two pointer approach works because of the following reasons.
- For every element in the first half, all valid elements in the second half form a prefix of the sorted right half.
- As we move toward right side of left half, the size of the prefix either increases or remains same.
Steps to implement the above idea:
- Sort the first half of the array in ascending order and the second half of the array in ascending order.
- Set a right pointer at the start of the second half.
- Iterate through the first half.
- For every element in the left half, move the right pointer forward while the dominance condition (arr[left] >= 5 * arr[right]) holds true.
- Update the result by adding count of right half elements before the right pointer.
// C++ Code to find number of dominant pairs
// using Sorting and Two Pointers
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int dominantPairs(vector<int> &arr) {
int n = arr.size();
// Sort the first half in ascending order
sort(arr.begin(), arr.begin() + n / 2);
// Sort the second half in ascending order
sort(arr.begin() + n / 2, arr.end());
int count = 0;
int right = n / 2;
// Iterate through the first half of the array
for (int left = 0; left < n / 2; left++) {
// Move right pointer while dominance condition holds
while (right < n && arr[left] >= 5 * arr[right]) {
right++;
}
// Count dominant pairs
count += (right - n / 2);
}
return count;
}
// Driver code
int main() {
vector<int> arr = {10, 2, 2, 1};
cout << dominantPairs(arr) << endl;
return 0;
}
// Java Code to find number of dominant pairs
// using Sorting and Two Pointers
import java.util.Arrays;
class GfG {
static int dominantPairs(int[] arr) {
int n = arr.length;
// Sort the first half in ascending order
Arrays.sort(arr, 0, n / 2);
// Sort the second half in ascending order
Arrays.sort(arr, n / 2, n);
int count = 0;
int right = n / 2;
// Iterate through the first half of the array
for (int left = 0; left < n / 2; left++) {
// Move right pointer while dominance condition holds
while (right < n && arr[left] >= 5 * arr[right]) {
right++;
}
// Count dominant pairs
count += (right - n / 2);
}
return count;
}
// Driver code
public static void main(String[] args) {
int[] arr = {10, 2, 2, 1};
System.out.println(dominantPairs(arr));
}
}
# Python Code to find number of dominant pairs
# using Sorting and Two Pointers
def dominantPairs(arr):
n = len(arr)
# Sort the first half in ascending order
arr[:n//2] = sorted(arr[:n//2])
# Sort the second half in ascending order
arr[n//2:] = sorted(arr[n//2:])
count = 0
right = n // 2
# Iterate through the first half of the array
for left in range(n // 2):
# Move right pointer while dominance condition holds
while right < n and arr[left] >= 5 * arr[right]:
right += 1
# Count dominant pairs
count += (right - n // 2)
return count
# Driver code
if __name__ == "__main__":
arr = [10, 2, 2, 1]
print(dominantPairs(arr))
// C# Code to find number of dominant pairs
// using Sorting and Two Pointers
using System;
class GfG {
static int dominantPairs(int[] arr) {
int n = arr.Length;
// Sort the first half in ascending order
Array.Sort(arr, 0, n / 2);
// Sort the second half in ascending order
Array.Sort(arr, n / 2, n - n / 2);
int count = 0;
int right = n / 2;
// Iterate through the first half of the array
for (int left = 0; left < n / 2; left++) {
// Move right pointer while dominance condition holds
while (right < n && arr[left] >= 5 * arr[right]) {
right++;
}
// Count dominant pairs
count += (right - n / 2);
}
return count;
}
// Driver code
public static void Main() {
int[] arr = {10, 2, 2, 1};
Console.WriteLine(dominantPairs(arr));
}
}
// JavaScript Code to find number of dominant pairs
// using Sorting and Two Pointers
function dominantPairs(arr) {
let n = arr.length;
// Sort the first half in ascending order
arr.splice(0, n / 2, ...arr.slice(0, n / 2).sort((a, b) => a - b));
// Sort the second half in ascending order
arr.splice(n / 2, n / 2, ...arr.slice(n / 2).sort((a, b) => a - b));
let count = 0;
let right = n / 2;
// Iterate through the first half of the array
for (let left = 0; left < n / 2; left++) {
// Move right pointer while dominance condition holds
while (right < n && arr[left] >= 5 * arr[right]) {
right++;
}
// Count dominant pairs
count += (right - n / 2);
}
return count;
}
// Driver code
let arr = [10, 2, 2, 1];
console.log(dominantPairs(arr));
Output
2
Time Complexity: O(n*log(n)), as sorting takes O(n log n), and two-pointer traversal takes O(n).
Space Complexity: O(1), as sorting is done in-place, and only a few extra variables are used.