刷题笔记:64 最大胜利次数问题 | 豆包MarsCode AI刷题

61 阅读3分钟

今天分享一道我个人认为非常有意思的题目与思路分析:是题库中的“英雄决斗的最大胜利次数”。 首先,展示题目如下:

问题描述

小U和小F正在进行一场由n轮组成的英雄决斗比赛。在每一轮中,小U和小F各自从他们的英雄队伍中选出一位英雄进行对决,英雄的能力值将决定比赛的胜负,能力值高者获胜。小U已经按照固定的能力顺序1, 2, 3, ..., n安排了他的英雄出场顺序。小F希望通过调整他的英雄出场顺序,最大化他的获胜轮数。我们的任务是帮助小F确定一个最佳的出场顺序,以获得最多的胜利。

解题思路

为了最大化胜利轮数,小F应该采用贪心策略,即用他最弱的英雄对抗小U最强的英雄,以此类推。具体步骤如下:

  1. 排序:首先,我们将小F的英雄按能力值从小到大排序。
  2. 匹配:接着,我们遍历小U的英雄,从小F的最弱英雄开始,尝试找到一个能击败小U当前英雄的最弱英雄。
  3. 标记:一旦找到合适的小F英雄,我们将其标记为已使用,并增加胜利轮数。

代码实现

以下是实现这一策略的Java代码:

import java.util.Arrays;
public class HeroDuel {
    public static int maxWins(int n, int[] heroes) {
        // 对小F的英雄按能力值从低到高排序
        Arrays.sort(heroes);
        
        int maxWins = 0;
        int[] usedHeroes = new int[n]; // 标记小F的英雄是否已被使用
        
        // 小U的英雄能力值从1到n
        for (int i = 0; i < n; i++) {
            // 从小F的最弱英雄开始,找到能击败小U当前英雄的最弱英雄
            for (int j = 0; j < n; j++) {
                if (usedHeroes[j] == 0 && heroes[j] > i + 1) {
                    // 如果找到能击败小U当前英雄的小F英雄,则标记为已使用并增加胜利轮数
                    usedHeroes[j] = 1;
                    maxWins++;
                    break;
                }
            }
        }
        return maxWins;
    }
    public static void main(String[] args) {
        int n = 5;
        int[] heroes = {3, 1, 4, 2, 5};
        System.out.println("小F可以获得的最大胜利轮数: " + maxWins(n, heroes));
    }
}

时间复杂度分析

  • 排序:对英雄数组进行排序的时间复杂度为O(n log n)。
  • 匹配:双重循环遍历英雄的时间复杂度为O(n^2)。
  • 总时间复杂度:因此,总的时间复杂度为O(n^2)。

空间复杂度分析

  • 除了输入数组外,我们只使用了额外的n个空间来标记已使用的英雄,因此空间复杂度为O(n)。 通过上述分析和代码实现,我们可以有效地帮助小F确定最佳的英雄出场顺序,以在英雄决斗比赛中获得最多的胜利。

补充

值得一提的是,在我完成这一题后,我想用ai助手帮助我检查是否存在缺陷,但ai的回答似乎存在一些不能自洽的地方,看起来似乎是对题目出现了理解上的偏差。我更换了其他大模型进行询问之后也依然如此,我想ai对于语意的理解应该还需要进一步加强。