刷题打卡 | 豆包MarsCode AI 刷题

82 阅读3分钟

英雄决斗比赛的胜利最大化

题目分析

小U和小F正在进行多轮决斗,每轮比赛各自派出英雄对决。小U的出场顺序固定为 1, 2, 3, ..., n,小F可以自由调整出场顺序,目标是使小F的胜利轮数尽可能多。

问题的关键是,小F需要找到一种英雄出场顺序,使得在尽可能多的轮次中,他的英雄能力值高于小U的英雄。

解题思路

我们可以将问题转化为一个双指针的排序匹配问题:

  1. 排序:先将小F的英雄能力值排序(从小到大),同时小U的英雄能力值已天然按照从小到大的顺序排列。
  2. 双指针模拟比赛:利用两个指针分别指向小U和小F当前的英雄出场位置,根据比赛结果调整指针和胜利计数:
    • 若小F的当前英雄能力值 大于 小U的当前英雄能力值,小F胜利,双方指针向后移动。
    • 若小F的当前英雄能力值 小于等于 小U的当前英雄能力值,则小F需要放弃当前英雄,用该英雄来消耗小U较弱的英雄,并移动相应指针。

算法步骤

  1. 将小F的英雄能力值数组 heroes 排序。
  2. 初始化两个指针:lalb 分别指向小U和小F的最左端;rarb 分别指向小U和小F的最右端。
  3. 模拟比赛过程:
    • heroes[rb] > u_heroes[ra],小F胜利,右端指针均左移。
    • heroes[rb] <= u_heroes[ra],尝试匹配小U最弱的英雄:
      • heroes[lb] > u_heroes[la],小F胜利,左端指针均右移。
      • 否则,小F的当前最弱英雄无法获胜,lb 右移,小U的最强英雄被消耗,ra 左移。

代码实现

以下为完整代码:

#include <bits/stdc++.h>
using namespace std;

int solution(int number, std::vector<int> heroes) {
    int res = 0;
    sort(heroes.begin(), heroes.end()); 
    vector<int> u_heroes(number); 
    for (int i = 0; i < number; ++i) {
        u_heroes[i] = i + 1;
    }
    int la = 0, lb = 0, ra = number - 1, rb = number - 1;
    while (la <= ra && lb <= rb) {
        if (heroes[rb] > u_heroes[ra]) {  // 小F的最强英雄击败小U的最强英雄
            ++res;
            --rb;
            --ra;
        } else if (heroes[rb] < u_heroes[ra]) {  // 小F的最强英雄无法胜利,消耗小U的最强英雄
            ++lb;
            --ra;
        } else {  // 小F的最强英雄与小U的最强英雄能力相等,尝试用小F的最弱英雄击败小U的最弱英雄
            if (heroes[lb] > u_heroes[la]) {  
                ++res;
                ++lb;
                ++la;
            } else {
                ++lb;
                --ra;
            }
        }
    }
    return res;
}

int main() {
    std::vector<int> heroes1 = {10,1,1,1,5,5,3};
    std::vector<int> heroes2 = {1,1,1,1,1};
    std::vector<int> heroes3 = {1,2,3,4,5,6,7,8,9,10};

    std::cout << (solution(7, heroes1) == 4) << std::endl;
    std::cout << (solution(5, heroes2) == 0) << std::endl;
    std::cout << (solution(10, heroes3) == 9) << std::endl;

    return 0;
}

复杂度分析

  1. 时间复杂度
    • 排序:O(n log n)
    • 双指针匹配:O(n)。 总时间复杂度为 O(n log n)
  2. 空间复杂度
    • 使用了两个数组存储小U和小F的英雄队伍,空间复杂度为 O(n)

测试样例

  • 样例1
    输入:heroes = [10,1,1,1,5,5,3], number = 7
    输出:4
    解释:调整后小F的最佳顺序为 [10,5,5,3,1,1,1],分别胜利 4 轮。

  • 样例2
    输入:heroes = [1,1,1,1,1], number = 5
    输出:0
    解释:小F的英雄均不可能胜利。

  • 样例3
    输入:heroes = [1,2,3,4,5,6,7,8,9,10], number = 10
    输出:9
    解释:小F可以通过调整顺序击败小U的所有英雄(除能力值为 10 的英雄)。

总结

本题的核心在于利用排序和双指针的贪心策略,最大化小F的胜利轮数。通过合理的匹配策略,我们确保每一次出场都尽可能多地消耗小U的强力英雄,或者保留小F的胜利可能性。