问题描述
小U和小F正在进行一场由 nn 轮组成的英雄决斗比赛。在每一轮中,小U和小F各自从他们的英雄队伍中选出一位英雄进行对决,英雄的能力值将决定比赛的胜负,能力值高者获胜。小U已经按照固定的能力顺序 1,2,3,…,n1,2,3,…,n 安排了他的英雄出场顺序。
小F希望通过调整他的英雄出场顺序,最大化他的获胜轮数。请帮助小 F 确定一个最佳的出场顺序,以获得最多的胜利。
输入说明
number: 一个整数,表示比赛的总轮数 nn。heroes: 一个长度为 nn 的正整数数组,表示小 F 的每个英雄的能力值。
输出
- 返回一个整数,表示小 F 可以获得的最大胜利轮数。
测试样例
样例1:
输入:
number = 7, heroes = [10, 1, 1, 1, 5, 5, 3]
输出:4
样例2:
输入:
number = 5, heroes = [1, 1, 1, 1, 1]
输出:0
样例3:
输入:
number = 6, heroes = [9, 4, 7, 3, 2, 6]
输出:6
思路解析
为了解决这个问题,我们需要分析如何让小F在比赛中尽可能地获胜。比赛的规则非常简单——在每一轮中,英雄能力值较高的一方获胜。所以,小F的目标是使得他的英雄能以最小的代价击败小U的英雄。
关键观察
- 小U的英雄能力值顺序:小U的英雄能力值是从1到n的顺序排列的,即小U的英雄依次是1, 2, 3, ..., n。
- 小F的英雄可以任意排列:小F可以自由选择英雄出场的顺序。为了最大化胜利,应该尽可能让小F的英雄击败小U的英雄,但也要避免浪费强力的英雄来对付小U的弱小英雄。
策略
为了尽可能多地获胜,我们可以采用以下策略:
- 贪心策略:对于每一轮比赛,小F应选择一个英雄来击败小U当前出场的英雄。如果小F的最小的英雄(目前还未使用的)能够击败小U当前出场的英雄,那么小F就应该派出该英雄获胜。否则,小F应该选择下一个英雄,直至找到可以获胜的英雄。
实现步骤
- 排序小F的英雄能力值:我们首先将小F的英雄按照能力值从小到大排序,方便从最小的英雄开始派遣。
- 双指针方法:我们使用两个指针分别指向小U和小F的英雄:
- 小U的指针从头开始,逐个遍历小U的英雄。
- 小F的指针也从头开始,但每次选择能击败小U当前英雄的最小英雄。
- 比赛规则:每当小F的英雄能击败小U的英雄时,我们增加胜利的轮数,且都指向下一个英雄。
- 终止条件:当小F或小U的英雄都用完时,比赛结束。
代码解析
def solution(number, heroes):
# 小U的英雄能力是固定的 [1, 2, 3, ..., number]
u_heroes = list(range(1, number + 1))
# 小F的英雄按能力值从小到大排序
f_heroes = sorted(heroes)
# 双指针法
u_index = 0 # 小U的当前英雄
f_index = 0 # 小F的当前英雄
wins = 0 # 小F获胜的轮数
# 遍历小U的每个英雄
while u_index < number and f_index < number:
if f_heroes[f_index] > u_heroes[u_index]: # 小F的英雄能打败小U的英雄
wins += 1
u_index += 1 # 小U英雄进入下一轮
# 不管是否胜利,都让小F的英雄进入下一轮
f_index += 1
return wins
代码解析
- u_heroes = list(range(1, number + 1)):构造一个长度为
number的列表,表示小U的英雄能力值。列表中的值从1开始递增。 - f_heroes = sorted(heroes):将小F的英雄能力值进行升序排序。这是因为我们希望用尽可能弱的英雄击败小U的强大英雄。
- 双指针:
u_index和f_index分别指向小U和小F当前出场的英雄,wins记录小F的胜利次数。if f_heroes[f_index] > u_heroes[u_index]:如果小F当前出场的英雄能力值大于小U当前出场的英雄能力值,那么小F获胜,增加胜利次数并推进两个指针。- 如果小F当前英雄无法击败小U的英雄,直接将小F的指针推进,表示小F出场下一个英雄。
示例分析
-
样例 1:
- 输入:
number = 7, heroes = [10, 1, 1, 1, 5, 5, 3] - 小U的英雄能力值为:[1, 2, 3, 4, 5, 6, 7]
- 小F的英雄能力值经过排序后为:[1, 1, 1, 3, 5, 5, 10]
- 小F的最佳策略是:用10击败7,用5击败6,用5击败5,用3击败4,最终小F赢得4轮。
- 输入:
-
样例 2:
- 输入:
number = 5, heroes = [1, 1, 1, 1, 1] - 小U的英雄能力值为:[1, 2, 3, 4, 5]
- 小F的英雄能力值为:[1, 1, 1, 1, 1]
- 小F没有足够强的英雄来击败小U的任何英雄,结果小F没有获胜,返回0。
- 输入:
-
样例 3:
- 输入:
number = 6, heroes = [9, 4, 7, 3, 2, 6] - 小U的英雄能力值为:[1, 2, 3, 4, 5, 6]
- 小F的英雄能力值为:[2, 3, 4, 6, 7, 9]
- 小F通过精妙安排可以在每轮比赛中获胜,结果返回6。
- 输入:
总结
这道题目通过贪心策略和双指针方法,优化了小F的英雄出场顺序,最大化了获胜的轮数。通过排序小F的英雄并逐轮与小U的英雄进行比较,能够在保证尽量少浪费强力英雄的同时,确保获得尽可能多的胜利。