【Leetcode】2410. 运动员和训练师的最大匹配数

题目描述

题目链接🔗
给你一个下标从 0 开始的整数数组 players ,其中 players[i] 是第 i 名运动员的能力。同样给你一个下标从 0 开始的整数数组 trainers ,其中 trainers[j] 是第 j 名训练师的训练能力。

如果第 i 名运动员的能力 小于等于j 名训练师的训练能力,那么第 i 名运动员可以 匹配j 名训练师。

返回满足上述条件 且能够匹配最大 运动员数目。

示例

示例 1:

输入:players = [4,7,9], trainers = [8,2,5,8]
输出:2
解释:
我们可以将运动员按如下方式匹配:
- 运动员 0 可以匹配训练师 0 ,因为 4 <= 8 。
- 运动员 1 可以匹配训练师 3 ,因为 7 <= 8 。
可以证明 2 是可以匹配的最大运动员数目。

示例 2:

输入:players = [1,1,1], trainers = [10]
输出:1
解释:
训练师可以被所有 3 个运动员匹配。
每个训练师最多可以匹配一个运动员,所以最多答案是 1 。

解题思路

这是一个典型的贪心算法问题。为了最大化匹配数量,我们应该:

  1. 贪心策略:让能力强的运动员匹配能力强的训练师,能力弱的运动员匹配能力弱的训练师
  2. 从大到小匹配:先处理能力最强的运动员和训练师,这样可以避免强训练师被弱运动员"浪费"

算法步骤

  1. 排序:对运动员数组和训练师数组进行升序排序
  2. 双指针:从两个数组的最大值开始,使用双指针进行匹配
  3. 匹配判断
    • 如果 players[i] <= trainers[j],则可以匹配,两个指针都向前移动
    • 如果 players[i] > trainers[j],则当前训练师无法匹配该运动员,只移动运动员指针
  4. 返回结果:返回成功匹配的运动员数量

代码实现

C++实现

class Solution {
public:
    int matchPlayersAndTrainers(vector<int>& players, vector<int>& trainers) {
        // 对两个数组进行排序
        sort(players.begin(), players.end());
        sort(trainers.begin(), trainers.end());
        
        // 双指针从最大值开始
        int idx1 = players.size() - 1;  // 运动员指针
        int idx2 = trainers.size() - 1; // 训练师指针
        int ans = 0;
        
        // 双指针匹配
        while (idx1 >= 0 && idx2 >= 0) {
            if (players[idx1] <= trainers[idx2]) {
                // 可以匹配,两个指针都向前移动
                idx1--;
                idx2--;
                ans++;
            } else {
                // 当前训练师无法匹配该运动员,只移动运动员指针
                idx1--;
            }
        }
        
        return ans;
    }
};

Java实现

class Solution {
    public int matchPlayersAndTrainers(int[] players, int[] trainers) {
        Arrays.sort(players);
        Arrays.sort(trainers);
        
        int idx1 = players.length - 1;
        int idx2 = trainers.length - 1;
        int ans = 0;
        
        while (idx1 >= 0 && idx2 >= 0) {
            if (players[idx1] <= trainers[idx2]) {
                idx1--;
                idx2--;
                ans++;
            } else {
                idx1--;
            }
        }
        
        return ans;
    }
}

Python实现

class Solution:
    def matchPlayersAndTrainers(self, players: List[int], trainers: List[int]) -> int:
        players.sort()
        trainers.sort()
        
        idx1 = len(players) - 1
        idx2 = len(trainers) - 1
        ans = 0
        
        while idx1 >= 0 and idx2 >= 0:
            if players[idx1] <= trainers[idx2]:
                idx1 -= 1
                idx2 -= 1
                ans += 1
            else:
                idx1 -= 1
        
        return ans

算法分析

正确性证明

贪心策略的正确性

  • 对于能力最强的运动员,如果有训练师能够匹配,我们应该选择能力最强的训练师
  • 这样可以为其他运动员保留更多的匹配机会
  • 如果最强的训练师都无法匹配最强的运动员,那么其他训练师也无法匹配

算法流程

  1. 从最强的运动员开始
  2. 如果当前最强的训练师可以匹配,则匹配
  3. 否则该运动员无法被任何训练师匹配,跳过
  4. 重复直到所有运动员或训练师都被处理

复杂度分析

  • 时间复杂度:O(n log n + m log m),其中 n 是运动员数量,m 是训练师数量
    • 排序:O(n log n + m log m)
    • 双指针遍历:O(n + m)
  • 空间复杂度:O(1),只使用了常数级额外空间

关键点总结

  1. 贪心思想:让强者配强者,避免资源浪费
  2. 排序预处理:为贪心策略提供基础
  3. 双指针技巧:高效地进行匹配判断
  4. 从大到小:确保贪心策略的正确性

这个算法通过贪心策略和双指针技巧,以最优的方式解决了运动员与训练师的匹配问题,是贪心算法的经典应用。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

想要AC的dly

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值