青训营X豆包MarsCode 英雄决斗的最大胜利次数 | 豆包MarsCode AI 刷题

73 阅读4分钟

选AI刷题中的“英雄决斗的最大胜利次数”题目进行分析。

问题描述

小U和小F正在进行一场由 nn 轮组成的英雄决斗比赛。在每一轮中,小U和小F各自从他们的英雄队伍中选出一位英雄进行对决,英雄的能力值将决定比赛的胜负,能力值高者获胜。小U已经按照固定的能力顺序 1,2,3,…,n1,2,3,…,n 安排了他的英雄出场顺序。

小F希望通过调整他的英雄出场顺序,最大化他的获胜轮数。请帮助小 F 确定一个最佳的出场顺序,以获得最多的胜利。

思路

  1. 排序:首先,我们对小F的英雄能力值进行排序,以便快速找到能够战胜小U英雄的最低能力值的小F英雄。

  2. 双指针遍历

    • 使用一个指针uHero表示小U当前英雄的能力值,从1遍历到number
    • 使用另一个指针j表示小F英雄的索引,从排序后的数组开始遍历。
    • 每次找到一个小F的英雄,其能力值大于小U当前英雄的能力值,则小F获胜一次,并将j指针向前移动一位,准备迎战小U的下一个英雄。
    • 如果当前小F的英雄能力值都不大于小U的英雄能力值,则小F无法赢得此次对战,继续遍历小U的下一个英雄。
  3. 计数:在遍历过程中,记录小F获胜的次数。

  • 排序Arrays.sort(heroes);

  • 双指针遍历

    • for (int uHero = 1; uHero <= number; uHero++):遍历小U的英雄。
    • while (j < heroes.length && heroes[j] <= uHero) { j++; }:找到小F中第一个能力值大于uHero的英雄。
    • if (j < heroes.length) { wins++; j++; }:如果找到,则记录胜利,并移动指针。
public class Main {
    public static int solution(int number, int[] heroes) {
        // Please write your code here
        // 对小F的英雄能力值进行排序  
        Arrays.sort(heroes);  
  
        int wins = 0;  // 胜利次数  
        int j = 0;     // 小F的英雄指针  
  
        // 遍历小U的英雄(假设小U的英雄能力值从1到number)  
        for (int uHero = 1; uHero <= number; uHero++) {  
            // 找到一个小F的英雄,能够战胜小U的英雄  
            while (j < number && heroes[j] <= uHero) {  
                j++;  
            }  
            // 如果找到了一个能战胜小U英雄的小F英雄,则增加胜利次数,并移动指针  
            if (j < number) {  
                wins++;  
                j++;  // 注意:这里的j++在Python代码中是为了跳过当前已经比较过的英雄,  
                      // 但在Java中,我们需要更仔细地考虑这个逻辑,因为每次循环都会增加uHero。  
                      // 然而,由于我们是在寻找第一个大于uHero的heroes[j],所以这里的j++是合理的,  
                      // 以避免与下一个uHero重复比较同一个heroes[j](如果它存在的话)。  
            }  
        }  
  
        return wins;  
        //return -2;
    }

    public static void main(String[] args) {
        //  You can add more test cases here
        int[] heroes1 = {10,1,1,1,5,5,3};
        int[] heroes2 = {1,1,1,1,1};
        int[] heroes3 = {1,2,3,4,5,6,7,8,9,10};

        System.out.println(solution(7, heroes1) == 4);
        System.out.println(solution(5, heroes2) == 0);
        System.out.println(solution(10, heroes3) == 9);

        System.out.println(solution(7, new int[]{10, 1, 1, 1, 5, 5, 3}) == 4);  
        System.out.println(solution(5, new int[]{1, 1, 1, 1, 1}) == 0);  
        System.out.println(solution(10, new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) == 9);  
    }
}

知识总结

新知识点

  1. 数组排序Arrays.sort(array); 方法可以对数组进行排序,这里使用的是升序排序。
  2. 双指针技巧:在处理两个有序数组或列表时,使用双指针可以高效地进行元素匹配和比较。
  3. 边界条件处理:在遍历和比较过程中,需要仔细处理数组边界和指针越界的问题。

理解与分析

  • 排序的重要性:排序为快速查找提供了基础,使得后续的比较和匹配更加高效。
  • 双指针的优势:双指针技巧通过减少不必要的比较,提高了算法的效率。
  • 边界条件的处理:在编写算法时,要特别注意指针的移动和数组边界的检查,以避免错误。

学习建议

  1. 理解基本概念:确保对排序算法和双指针技巧有基本的理解。
  2. 实践练习:通过大量的实践练习,加深对这两个概念的理解和掌握。
  3. 阅读源码:阅读和理解优秀代码中的排序和双指针技巧,可以提升自己的编程能力。
  4. 分享与讨论:与他人分享自己的代码和解题思路,通过讨论和反馈,不断改进和提高。