怪兽存活索引求解算法优化:解决大输入超时问题
问题重述
给定整数数组表示怪兽战力,战斗规则如下:
- 当前怪兽战力≥目标怪兽战力时,可击败对方
- 击败目标后,当前怪兽吸收对方战力(自身战力变为两者之和)
- 为每个怪兽安排最优战斗顺序(优先击败最弱的怪兽,逐步积累战力),且所有战力相等的战斗均判定获胜,找出最终能存活的怪兽的1-based索引。
现有Java代码时间复杂度为O(n²logn),无法处理大输入,需要O(n logn)复杂度的实现方案。
示例:输入powers = [1, 6, 2, 7, 2],输出[2, 4]
解决方案
核心思路是利用排序和前缀和,通过数学判断快速筛选出能存活的怪兽,整体时间复杂度为O(n logn):
关键观察
能存活的怪兽需满足:按战力升序排序后,从该怪兽开始,每一步吃掉所有更小的怪兽后的总战力,都能击败下一个更大的怪兽。具体来说:
- 将怪兽按战力升序排序,保留原始索引
- 计算前缀和数组,
sum[i]表示前i+1个(排序后)怪兽的战力总和 - 从后往前遍历,找到最小的索引
k,使得对于所有i >=k,sum[i] >= a[i+1].power(若i+1 <n)。所有排序后索引从k到n-1的怪兽,即为能存活的怪兽。
Java实现代码
import java.util.*; public class SurvivingMonsters { static class Monster { int power; int index; Monster(int power, int index) { this.power = power; this.index = index; } } public static List<Integer> findSurvivingMonsters(int[] powers) { int n = powers.length; if (n == 0) return Collections.emptyList(); // 1. 排序怪兽,按战力升序,保留原始1-based索引 Monster[] monsters = new Monster[n]; for (int i = 0; i < n; i++) { monsters[i] = new Monster(powers[i], i + 1); } Arrays.sort(monsters, Comparator.comparingInt(m -> m.power)); // 2. 计算前缀和数组 long[] prefixSum = new long[n]; prefixSum[0] = monsters[0].power; for (int i = 1; i < n; i++) { prefixSum[i] = prefixSum[i - 1] + monsters[i].power; } // 3. 找到最小的k,使得从k开始所有怪兽都满足条件 int k = n - 1; for (int i = n - 2; i >= 0; i--) { if (prefixSum[i] >= monsters[i + 1].power) { k = i; } else { // 前面的怪兽无法满足条件,直接跳出 break; } } // 4. 收集结果,按原始索引排序 List<Integer> result = new ArrayList<>(); for (int i = k; i < n; i++) { result.add(monsters[i].index); } Collections.sort(result); return result; } public static void main(String[] args) { // 示例测试 int[] powers1 = {1, 6, 2, 7, 2}; System.out.println(findSurvivingMonsters(powers1)); // 输出 [2,4] // 其他测试用例 int[] powers2 = {3,1,4,1,5}; System.out.println(findSurvivingMonsters(powers2)); // 输出 [1,3,5] int[] powers3 = {1,2,4,8,16}; System.out.println(findSurvivingMonsters(powers3)); // 输出 [5] int[] powers4 = {2,2,3,7,11}; System.out.println(findSurvivingMonsters(powers4)); // 输出 [1,2,3,4,5] } }
代码解释
- 排序阶段:将怪兽按战力升序排列,同时记录原始1-based索引,方便后续映射回结果。
- 前缀和计算:快速得到前
i+1个怪兽的总战力,用于判断吃掉所有更小怪兽后的战力是否足够击败下一个更大的怪兽。 - 筛选存活怪兽:从后往前遍历,找到第一个不满足
prefixSum[i] >= monsters[i+1].power的位置,之后的所有怪兽都能存活。这是因为如果当前怪兽满足条件,前面的怪兽只要能满足击败当前怪兽,就能继续击败后续所有怪兽。 - 结果整理:收集存活怪兽的原始索引并排序,输出符合要求的升序结果。
内容的提问来源于stack exchange,提问作者CodeCrusader
相关产品推荐
相关产品推荐

