Maximize Count Of Increasing Pairs

Last Updated : 24 Oct, 2025

Given two arrays a1[] and a2[], find the maximum number of pairs (i, j), such that 2*a1[i] ≤ a2[j].

Note: Any array element can be part of a single pair.

Examples:

Input: a1[] = [3, 1, 2], a2[] = [3, 4, 2, 1]
Output: 2
Explanation: Only two pairs can be chosen:
(1, 3): Choose elements a1[2] and a2[1].
(2, 2): Choose elements a1[3] and a2[2].

Input: a1[] = [40], a2[] = [10, 20, 30, 40]
Output: 0
Explanation: There is no such pair exists.

[Naive Approach]: Using Sorting - O(n*m) Time and O(n+m) Space

The simplest approach is to first sort both the arrays and Then, for each element in a1[], calculate 2*a1[i] and find the first unused element in a2[] that is greater than or equal to this value, for finding the first unused element we will use a visited array, after we found a valid pair we will mark that element as used (using a visited array) and increment the pair count. This ensures each element in a2[] is used at most once while maximizing valid pairs.

C++
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int numberOfPairs(vector<int>& a1, vector<int>& a2) {
    
    // Sort both arrays
    sort(a1.begin(), a1.end());
    sort(a2.begin(), a2.end());
    
    int count = 0;
    
    // Track used elements from a2
    vector<bool> visited(a2.size(), false);  

    // Traverse a1[]
    for (int i = 0; i < a1.size(); i++) {
        int target = 2 * a1[i];

        // Traverse a2[] to find first unused element >= target
        for (int j = 0; j < a2.size(); j++) {
            if (!visited[j] && a2[j] >= target) {
                count++;
                
                // Mark as used
                visited[j] = true;  
                break;              
            }
        }
    }

    return count;
}

// Driver code
int main() {
    vector<int> a1 = {3, 1, 2};
    vector<int> a2 = {3, 4, 2, 1};

    int ans = numberOfPairs(a1, a2);
    cout << ans << endl;

    return 0;
}
Java
import java.util.*;

public class Main {

    static int numberOfPairs(int[] a1, int[] a2) {

        // Sort both arrays
        Arrays.sort(a1);
        Arrays.sort(a2);

        int count = 0;
        
        // Track used elements from a2
        boolean[] visited = new boolean[a2.length];  

        // Traverse a1[]
        for (int i = 0; i < a1.length; i++) {
            int target = 2 * a1[i];

            // Traverse a2[] to find first unused element >= target
            for (int j = 0; j < a2.length; j++) {
                if (!visited[j] && a2[j] >= target) {
                    count++;
                    
                    // Mark as used
                    visited[j] = true;  
                    break;              
                }
            }
        }

        return count;
    }

    // Driver code
    public static void main(String[] args) {
        int[] a1 = {3, 1, 2};
        int[] a2 = {3, 4, 2, 1};

        int ans = numberOfPairs(a1, a2);
        System.out.println(ans);
    }
}
Python
def numberOfPairs(a1, a2):
    # Sort both arrays
    a1.sort()
    a2.sort()

    count = 0
    
    # Track used elements from a2
    visited = [False] * len(a2) 

    # Traverse a1[]
    for i in range(len(a1)):
        target = 2 * a1[i]

        # Traverse a2[] to find first unused element >= target
        for j in range(len(a2)):
            if not visited[j] and a2[j] >= target:
                count += 1
                
                # Mark as used
                visited[j] = True  
                break  

    return count


# Driver code
a1 = [3, 1, 2]
a2 = [3, 4, 2, 1]

ans = numberOfPairs(a1, a2)
print(ans)
C#
using System;

class Program
{
    static int NumberOfPairs(int[] a1, int[] a2)
    {
        // Sort both arrays
        Array.Sort(a1);
        Array.Sort(a2);

        int count = 0;
        
        // Track used elements from a2
        bool[] visited = new bool[a2.Length];  

        // Traverse a1[]
        for (int i = 0; i < a1.Length; i++)
        {
            int target = 2 * a1[i];

            // Traverse a2[] to find first unused element >= target
            for (int j = 0; j < a2.Length; j++)
            {
                if (!visited[j] && a2[j] >= target)
                {
                    count++;
                    
                    // Mark as used
                    visited[j] = true; 
                    break;             
                }
            }
        }

        return count;
    }

    // Driver code
    static void Main()
    {
        int[] a1 = { 3, 1, 2 };
        int[] a2 = { 3, 4, 2, 1 };

        int ans = NumberOfPairs(a1, a2);
        Console.WriteLine(ans);
    }
}
JavaScript
function numberOfPairs(a1, a2) {
  // Sort both arrays
  a1.sort((a, b) => a - b);
  a2.sort((a, b) => a - b);

  let count = 0;

  // Track used elements from a2
  let visited = new Array(a2.length).fill(false);

  // Traverse a1[]
  for (let i = 0; i < a1.length; i++) {
    let target = 2 * a1[i];

    // Traverse a2[] to find first unused element >= target
    for (let j = 0; j < a2.length; j++) {
      if (!visited[j] && a2[j] >= target) {
        count++;

        // Mark as used
        visited[j] = true;
        break;
      }
    }
  }

  return count;
}

// Driver code
const a1 = [3, 1, 2];
const a2 = [3, 4, 2, 1];

const ans = numberOfPairs(a1, a2);
console.log(ans);

Output
2

[Expected Approach 1]: Using Two Pointers – O(n*logn + m*logm) Time and O(1) Space

In this, we will first sort both arrays, and then the idea is to use the Two-Pointer Technique to find an element in a2[] that is just greater than or equal to 2*a1[i]. We start with two pointers — one for a1[] and one for a2[]. If a2[j] is greater than or equal to 2*a1[i], we have found a valid pair, so we increment both pointers. Otherwise, we move the a2 pointer ahead to find a suitable match. This process continues until we traverse one of the arrays, ensuring the maximum number of valid pairs.

C++
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int numberOfPairs(vector<int>& a1, vector<int>& a2) {

    // Sort both arrays
    sort(a1.begin(), a1.end());
    sort(a2.begin(), a2.end());

    int count = 0;
    
     // Two pointers
    int i = 0, j = 0; 

    // Traverse both arrays
    while (i < a1.size() && j < a2.size()) {
        int target = 2 * a1[i];

        // If a2[j] satisfies condition, form a pair
        if (a2[j] >= target) {
            count++;
            i++;
            j++;
        } 
        
        // Otherwise, move j to find a bigger element
        else {
            j++;
        }
    }

    return count;
}

// Driver code
int main() {
    vector<int> a1 = {3, 1, 2};
    vector<int> a2 = {3, 4, 2, 1};

    int ans = numberOfPairs(a1, a2);
    cout << ans << endl;

    return 0;
}
Java
import java.util.Arrays;

public class Main {

    static int numberOfPairs(int[] a1, int[] a2) {

        // Sort both arrays
        Arrays.sort(a1);
        Arrays.sort(a2);

        int count = 0;
        int i = 0, j = 0;

        // Traverse both arrays using two pointers
        while (i < a1.length && j < a2.length) {
            int target = 2 * a1[i];

            // If a2[j] satisfies condition, form a pair
            if (a2[j] >= target) {
                count++;
                i++;
                j++;
            }
            
            // Otherwise, move j to find a bigger element
            else {
                j++;
            }
        }

        return count;
    }

    // Driver code
    public static void main(String[] args) {
        int[] a1 = {3, 1, 2};
        int[] a2 = {3, 4, 2, 1};

        int ans = numberOfPairs(a1, a2);
        System.out.println(ans);
    }
}
Python
def numberOfPairs(a1, a2):

    # Sort both lists
    a1.sort()
    a2.sort()

    count = 0
    
    # Two pointers
    i, j = 0, 0

    # Traverse both lists
    while i < len(a1) and j < len(a2):
        target = 2 * a1[i]

        # If a2[j] satisfies condition, form a pair
        if a2[j] >= target:
            count += 1
            i += 1
            j += 1

        # Otherwise, move j to find a bigger element
        else:
            j += 1

    return count


# Driver code
if __name__ == "__main__":
    a1 = [3, 1, 2]
    a2 = [3, 4, 2, 1]

    ans = numberOfPairs(a1, a2)
    print(ans)
C#
using System;

class Program
{
    static int NumberOfPairs(int[] a1, int[] a2)
    {
        // Sort both arrays
        Array.Sort(a1);
        Array.Sort(a2);

        int count = 0;
        int i = 0, j = 0;

        // Two-pointer traversal
        while (i < a1.Length && j < a2.Length)
        {
            int target = 2 * a1[i];

            // If a2[j] satisfies the condition, form a pair
            if (a2[j] >= target)
            {
                count++;
                i++;
                j++;
            }
            else
            {
                j++;
            }
        }

        return count;
    }

    // Driver code
    static void Main()
    {
        int[] a1 = { 3, 1, 2 };
        int[] a2 = { 3, 4, 2, 1 };

        int ans = NumberOfPairs(a1, a2);
        Console.WriteLine(ans);
    }
}
JavaScript
function numberOfPairs(a1, a2) {

    // Sort both arrays
    a1.sort((a, b) => a - b);
    a2.sort((a, b) => a - b);

    let count = 0;

    // Two pointers
    let i = 0, j = 0;

    // Traverse both arrays
    while (i < a1.length && j < a2.length) {
        let target = 2 * a1[i];

        // If a2[j] satisfies condition, form a pair
        if (a2[j] >= target) {
            count++;
            i++;
            j++;
        } 
        // Otherwise, move j to find a bigger element
        else {
            j++;
        }
    }

    return count;
}

// Driver code
const a1 = [3, 1, 2];
const a2 = [3, 4, 2, 1];

const ans = numberOfPairs(a1, a2);
console.log(ans);

Output
2

[Expected Approach 2]: Using Max Heap– O(n*logn + m*logm) Time and O(1) Space

The idea is to use the Greedy Algorithm for finding an element in a2[] that is just greater than or equal to the value 2*a1[i], we will use max heap which will arrange all the elements of a2[] in descending order and it's top element represents the largest element which will allows us efficient access and removal of the largest element each time, which helps in finding a suitable pair for each element of a1[].

Steps to solve the problem:

  • Sort the array a1[] and initialize a variable ans to store the maximum number of pairs.
  • Add all the elements of a2[] in a Max Heap.
  • Traverse the array a1[] from i = (n - 1) to 0 in non-increasing order.
  • For each element a1[i], remove the peek element from the Max Heap until 2*a1[i] becomes smaller than or equal to the peek element and increment ans by 1 if such element is found.
C++
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;

int numberOfPairs(vector<int> &a1, vector<int> &a2)
{
    int n = a1.size();
    int m = a2.size();
    priority_queue<int> pq;
    int i, j;

    // Sort the array a1[]
    sort(a1.begin(),a1.end());

    // Push all arr2[] into Max Heap
    for (j = 0; j < m; j++) {
        pq.push(a2[j]);
    }

    int ans = 0;

    // Traverse the arr1[] in decreasing order
    for (i = n - 1; i >= 0; i--) {

        // Remove element until a
        // required pair is found
        if (pq.top() >= 2 * a1[i]) {
            ans++;
            pq.pop();
        }
    }
    return ans;
}

int main()
{
    vector<int> a1 = {3, 1, 2};
    vector<int> a2 = {3, 4, 2, 1};

    cout << numberOfPairs(a1, a2);
    return 0;
}
Java
import java.util.*;

public class Main {

    static int numberOfPairs(int[] a1, int[] a2) {
        
        int n = a1.length;
        int m = a2.length;
        
        // Max Heap to add values of arr2[]
        PriorityQueue<Integer> pq = new PriorityQueue<>(Collections.reverseOrder());

        // Sort the array arr1[]
        Arrays.sort(a1);

        // Push all arr2[] into Max Heap
        for (int j = 0; j < m; j++) {
            pq.add(a2[j]);
        }

        int ans = 0;

        // Traverse the arr1[] in decreasing order
        for (int i = n - 1; i >= 0; i--) {
            // Remove element until a required pair is found
            if (!pq.isEmpty() && pq.peek() >= 2 * a1[i]) {
                ans++;
                pq.poll();
            }
        }
        return ans;
    }

    public static void main(String[] args) {
        // Given arrays
        int[] a1 = {3, 1, 2};
        int[] a2 = {3, 4, 2, 1};

        int N = a1.length;
        int M = a2.length;

        System.out.println(numberOfPairs(a1, a2));
    }
}
Python
import heapq

def numberOfPairs(a1, a2):
    
    n = len(a1)
    m = len(a2)
    
    # Max Heap to add values of arr2[]
    pq = []
    
    # Sort the array arr1[]
    a1.sort()
    
    # Push all arr2[] into Max Heap (use negative for max-heap behavior)
    for j in range(m):
        heapq.heappush(pq, -a2[j])
    
    ans = 0
    
    # Traverse the arr1[] in decreasing order
    for x in reversed(a1):
        if pq and -pq[0] >= 2 * x:
            ans += 1
            heapq.heappop(pq)
    
    return ans


if __name__ == '__main__':
    
    # Given arrays
    a1 = [3, 1, 2]
    a2 = [3, 4, 2, 1]
    
    print(numberOfPairs(a1, a2))
C#
using System;
using System.Collections.Generic;

class GFG
{
    static int NumberOfPairs(int[] a1, int[] a2)
    {
        int n = a1.Length;
        int m = a2.Length;
        
        // Max Heap to add values of arr2[]
        List<int> pq = new List<int>();
        int i, j;

        // Sort the array arr1[]
        Array.Sort(a1);

        // Push all arr2[] into Max Heap
        for (j = 0; j < m; j++)
        {
            pq.Add(a2[j]);
        }

        int ans = 0;

        // Traverse the arr1[] in decreasing order
        for (i = n - 1; i >= 0; i--)
        {
            if (pq.Count == 0)
                break;

            // Sort pq in descending order (simulate max-heap behavior)
            pq.Sort((a, b) => b.CompareTo(a));

            // Remove element until a required pair is found
            if (pq[0] >= 2 * a1[i])
            {
                ans++;
                pq.RemoveAt(0);
            }
        }
        return ans;
    }

    static void Main()
    {
        // Given arrays
        int[] a1 = { 3, 1, 2 };
        int[] a2 = { 3, 4, 2, 1 };

        Console.WriteLine(NumberOfPairs(a1, a2));
    }
}
JavaScript
function numberOfPairs(a1, a2) {
    const n = a1.length;
    const m = a2.length;

    // Max Heap to add values of arr2[]
    let pq = [];

    // Sort the array arr1[]
    a1.sort((a, b) => a - b);

    // Push all arr2[] into Max Heap
    for (let j = 0; j < m; j++)
        pq.push(a2[j]);

    let ans = 0; 

    // Traverse the arr1[] in decreasing order
    let i = n - 1;
    while (i >= 0) {

        // Sort pq in decreasing order (simulate max heap)
        pq.sort((a, b) => b - a);

        if (pq.length === 0)
            break;

        // Remove element until a required pair is found
        if (pq[0] >= 2 * a1[i]) {
            ans += 1;
            pq.shift(); // remove top element
        }

        i -= 1;
    }
    return ans;
}

// Driver Code

let a1 = [3, 2, 1];
let a2 = [3, 4, 2, 1];

// Function Call
console.log(numberOfPairs(a1, a2));

Output
2
Comment