{x}
blog image

Maximum Matching of Players With Trainers

You are given a 0-indexed integer array players, where players[i] represents the ability of the ith player. You are also given a 0-indexed integer array trainers, where trainers[j] represents the training capacity of the jth trainer.

The ith player can match with the jth trainer if the player's ability is less than or equal to the trainer's training capacity. Additionally, the ith player can be matched with at most one trainer, and the jth trainer can be matched with at most one player.

Return the maximum number of matchings between players and trainers that satisfy these conditions.

 

Example 1:

Input: players = [4,7,9], trainers = [8,2,5,8]
Output: 2
Explanation:
One of the ways we can form two matchings is as follows:
- players[0] can be matched with trainers[0] since 4 <= 8.
- players[1] can be matched with trainers[3] since 7 <= 8.
It can be proven that 2 is the maximum number of matchings that can be formed.

Example 2:

Input: players = [1,1,1], trainers = [10]
Output: 1
Explanation:
The trainer can be matched with any of the 3 players.
Each player can only be matched with one trainer, so the maximum answer is 1.

 

Constraints:

  • 1 <= players.length, trainers.length <= 105
  • 1 <= players[i], trainers[j] <= 109

 

Note: This question is the same as 445: Assign Cookies.

2410. Maximum Matching of Players With Trainers

Problem Description

Given two arrays players and trainers, where players[i] represents the ability of the ith player and trainers[j] represents the training capacity of the jth trainer, find the maximum number of matchings between players and trainers such that the player's ability is less than or equal to the trainer's capacity. Each player and trainer can only be matched once.

Solution: Greedy Approach with Two Pointers

The optimal solution uses a greedy approach combined with two pointers. The idea is to sort both the players and trainers arrays in ascending order. Then, we iterate through the sorted players array using a pointer i. For each player, we iterate through the sorted trainers array using a pointer j, starting from where we left off in the previous iteration. We find the first trainer whose capacity is greater than or equal to the current player's ability. If we find a match, we increment both i and j and continue. If we reach the end of the trainers array without finding a match for the current player, it means no more matches are possible, and we return the current number of matches found so far. If we successfully iterate through all players, it means all players found a match, and we return the total number of players.

Time and Space Complexity

  • Time Complexity: O(m log m + n log n), where m is the length of players and n is the length of trainers. This is dominated by the sorting of the two arrays. The two-pointer iteration is linear in the smaller of m and n.
  • Space Complexity: O(log m + log n) or O(1) depending on the sorting implementation. In-place sorting algorithms would result in O(1) space complexity.

Code Implementation

Here's the code implementation in several programming languages:

Python:

def matchPlayersAndTrainers(players, trainers):
    players.sort()
    trainers.sort()
    i, j = 0, 0
    count = 0
    while i < len(players) and j < len(trainers):
        if players[i] <= trainers[j]:
            count += 1
            i += 1
            j += 1
        else:
            j += 1
    return count
 

Java:

import java.util.Arrays;
 
class Solution {
    public int matchPlayersAndTrainers(int[] players, int[] trainers) {
        Arrays.sort(players);
        Arrays.sort(trainers);
        int i = 0, j = 0, count = 0;
        while (i < players.length && j < trainers.length) {
            if (players[i] <= trainers[j]) {
                count++;
                i++;
                j++;
            } else {
                j++;
            }
        }
        return count;
    }
}

C++:

#include <algorithm>
#include <vector>
 
class Solution {
public:
    int matchPlayersAndTrainers(std::vector<int>& players, std::vector<int>& trainers) {
        std::sort(players.begin(), players.end());
        std::sort(trainers.begin(), trainers.end());
        int i = 0, j = 0, count = 0;
        while (i < players.size() && j < trainers.size()) {
            if (players[i] <= trainers[j]) {
                count++;
                i++;
                j++;
            } else {
                j++;
            }
        }
        return count;
    }
};

JavaScript:

/**
 * @param {number[]} players
 * @param {number[]} trainers
 * @return {number}
 */
var matchPlayersAndTrainers = function(players, trainers) {
    players.sort((a, b) => a - b);
    trainers.sort((a, b) => a - b);
    let i = 0, j = 0, count = 0;
    while (i < players.length && j < trainers.length) {
        if (players[i] <= trainers[j]) {
            count++;
            i++;
            j++;
        } else {
            j++;
        }
    }
    return count;
};

These code snippets all implement the same greedy two-pointer algorithm, demonstrating its efficiency and adaptability across different programming languages. Remember that the efficiency hinges on the efficient sorting algorithms used by each language's sort() function.