小U和小F的英雄对决 | 豆包MarsCode AI刷题

42 阅读9分钟

一、思路分析

  1. 整体策略

    • 本题的目标是帮助小 F 通过合理安排英雄出场顺序,最大化其在与小 U 的英雄决斗比赛中的获胜轮数。由于小 U 的英雄出场顺序是固定的按照能力值从 1 到 n 递增,所以我们需要考虑如何安排小 F 的英雄出场顺序来尽可能多地赢得比赛。
    • 核心思路是利用排序和双指针法来比较小 F 和小 U 的英雄能力值,从而确定小 F 能获得的最大胜利轮数。
  2. 排序的作用

    • 首先对小 F 的英雄能力值数组 heroes 进行排序。这样做的好处是,经过排序后,小 F 的英雄能力值会呈现出一种有序的状态,便于后续与小 U 的固定顺序的英雄能力值进行比较。例如,如果小 F 的英雄能力值未排序,那么在比较时可能会出现混乱的情况,难以确定最佳的出场顺序以获得最多胜利。而排序后,我们可以从能力值较小的一端开始,逐步与小 U 的英雄进行比较,更有策略地安排对决。
  3. 双指针法的运用

    • 定义了两个指针 u_index 和 f_index,分别用于指向小 U 和小 F 的英雄。通过同时移动这两个指针,依次比较小 F 和小 U 当前所指英雄的能力值。
    • 当 heroes[f_index] > u_heroes[u_index] 时,意味着小 F 的当前英雄能力值大于小 U 的当前英雄能力值,小 F 的英雄获胜,此时将胜利计数 wins 加 1,并将小 U 的指针 u_index 向前移动一位,准备下一轮比较。
    • 无论本轮比较结果是小 F 的英雄胜利还是失败,小 F 的指针 f_index 都要向前移动一位,以便继续进行下一轮比较。这样持续比较下去,直到其中一方的指针超出了比赛的总轮数 number,此时循环结束,返回胜利计数 wins,即为小 F 可以获得的最大胜利轮数。

二、图解(以样例 1:number = 7, heroes = [10, 1, 1, 1, 5, 5, 3] 为例)

1. 初始化阶段

  • 首先,小 U 的英雄能力值按照固定顺序生成,即 u_heroes = [1, 2, 3, 4, 5, 6, 7]

  • 对小 F 的英雄能力值数组 heroes 进行排序,得到 [1, 1, 1, 3, 5, 5, 10]

  • 初始化指针 u_index = 0f_index = 0,胜利计数 wins = 0

2. 比较阶段

  • 第一轮比较:

    • u_heroes[u_index] = 1heroes[f_index] = 1,因为 1 = 1(不满足 heroes[f_index] > u_heroes[u_index]),小 F 的英雄本轮未获胜。
    • f_index 移动到下一位,f_index = 1
  • 第二轮比较:

    • u_heroes[u_index] = 1heroes[f_index] = 1,同样未获胜,f_index = 2
  • 第三轮比较:

    • u_heroes[u_index] = 1heroes[f_index] = 1,还是未获胜,f_index = 3
  • 第四轮比较:

    • u_heroes[u_index] = 1heroes[f_index] = 3,此时 3 > 1,小 F 的英雄获胜。
    • wins 增加 1,变为 1
    • u_index 移动到下一位,u_index = 1
    • f_index 移动到下一位,f_index = 4
  • 第五轮比较:

    • u_heroes[u_index] = 2heroes[f_index] = 5,因为 5 > 2,小 F 的英雄获胜。
    • wins 增加 1,变为 2
    • u_index 移动到下一位,u_index = 2
    • f_index 移动到下一位,f_index = 5
  • 第六轮比较:

    • u_heroes[u_index] = 3heroes[f_index] = 5,因为 5 > 3,小 F 的英雄获胜。
    • wins 增加 1,变为 3
    • u_index 移动到下一位,u_index = 3
    • f_index 移动到下一位,f_index = 6
  • 第七轮比较:

    • u_heroes[u_index] = 4heroes[f_index] = 10,因为 10 > 4,小 F 的英雄获胜。

    • wins 增加 1,变为 4

    • u_index 移动到下一位,u_index = 4

    • f_index 移动到下一位,f_index = 7

此时,f_index 和 u_index 都已经达到了 number = 7,比较结束,最终小 F 可以获得的最大胜利轮数为 4

三、代码详解

收起

python

复制

def solution(number, heroes):
    # 小U的英雄能力值是固定的,从1到number
    u_heroes = list(range(1, number + 1))

    # 对小F的英雄能力值进行排序
    heroes.sort()

    u_index = 0  # 小U的英雄指针
    f_index = 0  # 小F的英雄指针
    wins = 0      # 胜利计数

    # 使用双指针法进行比较
    while u_index < number and f_index < number:
        if heroes[f_index] > u_heroes[u_index]:
            # 小F的英雄胜利
            wins += 1
            u_index += 1  # 移动小U的指针
        # 无论胜负,小F的指针都要移动
        f_index += 1

    return wins
  1. u_heroes = list(range(1, number + 1))

    • 这行代码根据输入的比赛总轮数 number,生成了小 U 的英雄能力值数组 u_heroes,其值按照从 1 到 number 的顺序依次递增,这是小 U 固定的英雄出场顺序所对应的能力值情况。
  2. heroes.sort()

    • 对小 F 的英雄能力值数组 heroes 进行排序操作,使得 heroes 中的元素按照从小到大的顺序排列。这样在后续与小 U 的英雄能力值进行比较时,可以更有序地进行判断,以便找到小 F 获得最多胜利的出场顺序。
  3. u_index = 0f_index = 0wins = 0

    • 分别初始化了三个变量。u_index 用于指向小 U 的英雄,初始化为 0,表示从第一个英雄开始比较;f_index 用于指向小 F 的英雄,同样初始化为 0;wins 用于记录小 F 的胜利轮数,初始化为 0。
  4. while u_index < number and f_index < number:

    • 这是一个循环条件,只要小 U 和小 F 的指针都没有超出比赛的总轮数 number,就会继续循环进行比较。
  5. if heroes[f_index] > u_heroes[u_index]:

    • 在循环内部,首先进行比较判断。如果小 F 当前所指英雄的能力值(heroes[f_index])大于小 U 当前所指英雄的能力值(u_heroes[u_index]),那么说明小 F 的英雄在本轮获胜。
  6. wins += 1u_index += 1

    • 当小 F 的英雄获胜时,将胜利计数 wins 增加 1,表示小 F 又赢得了一轮比赛;同时将小 U 的指针 u_index 向前移动一位,准备下一轮比较,因为小 U 在每一轮比赛后会按照固定顺序派出下一个英雄。
  7. f_index += 1

    • 无论本轮比较结果是小 F 的英雄胜利还是失败,都要将小 F 的指针 f_index 向前移动一位,以便继续进行下一轮比较,确保能够遍历完小 F 的所有英雄。
  8. return wins

    • 在循环结束后,也就是当小 U 或小 F 的指针超出了比赛总轮数 number 时,返回胜利计数 wins,这个值就是小 F 可以获得的最大胜利轮数。

四、知识总结

新知识点梳理与分析

  1. 排序算法的应用

    • 在本题中,对小 F 的英雄能力值数组 heroes 进行排序是一个关键步骤。排序使得数组元素呈现出有序的状态,便于后续与小 U 的固定顺序的英雄能力值进行比较和匹配。常见的排序算法有冒泡排序、插入排序、快速排序等,本题使用的是 Python 内置的排序函数 sort(),它通常采用的是一种高效的排序算法(如快速排序的变种),能够在较短的时间内将数组排序。理解排序算法的作用以及如何根据具体问题选择合适的排序算法对于解决很多涉及数据比较和匹配的问题非常重要。
  2. 双指针法

    • 双指针法是本题解决问题的核心算法之一。通过定义两个指针分别指向不同的数组(在本题中分别指向小 U 和小 F 的英雄能力值数组),并通过同时移动这两个指针来进行数据的比较和处理。双指针法在很多数组相关的问题中都有广泛的应用,比如在查找数组中满足一定条件的元素对、合并两个有序数组等问题中都可以发挥很好的作用。它的优点在于能够通过简单的指针移动操作,高效地遍历数组并进行相关的计算和判断,减少了不必要的循环嵌套和复杂的逻辑判断。

理解与学习建议

  • 理解

    • 要理解本题的解法,首先要明白排序和双指针法在整个解题过程中的作用。排序是为了让小 F 的英雄能力值数组有序,以便更好地与小 U 的固定顺序的英雄能力值进行比较;双指针法是通过同时移动两个指针来高效地进行比较和判断,从而确定小 F 的最大胜利轮数。要深入理解每个步骤之间的逻辑关系,比如为什么在小 F 的英雄获胜时要移动小 U 的指针,以及为什么无论胜负都要移动小 F 的指针等。
  • 学习建议

    • 对于排序算法,建议初学者先学习几种常见的排序算法,如冒泡排序、插入排序、快速排序等,了解它们的基本原理、算法步骤以及时间复杂度和空间复杂度等特性。可以通过手动模拟排序过程来加深理解,比如自己动手写代码实现冒泡排序,观察数组元素是如何逐步排序的。同时,要熟悉 Python 内置的排序函数 sort() 和 sorted() 的用法和区别,以便在实际编程中能够灵活运用。
    • 对于双指针法,要多做一些涉及双指针应用的练习题,如在数组中查找两个数之和等于给定值、合并两个有序数组等问题。通过大量的练习,熟悉双指针法的不同应用场景和操作方式,掌握如何根据具体问题设置指针的初始位置、移动规则以及判断条件等。在解决问题时,要先分析问题的本质需求,看看是否可以通过双指针法来解决,然后再动手写代码。

代码中的变量w具体代表什么含义?

除了双指针法,还有哪些方法可以解决这个问题?

这个问题可以应用到哪些实际场景中?