Skip to content

2214. Minimum Health to Beat Game πŸ”’

DifficultyMedium

Description

You are playing a game that has n levels numbered from 0 to n - 1. You are given a 0-indexed integer array damage where damage[i] is the amount of health you will lose to complete the ith level.

You are also given an integer armor. You may use your armor ability at most once during the game on any level which will protect you from at most armor damage.

You must complete the levels in order and your health must be greater than 0 at all times to beat the game.

Return the minimum health you need to start with to beat the game.

 

Example 1:

Input: damage = [2,7,4,3], armor = 4
Output: 13
Explanation: One optimal way to beat the game starting at 13 health is:
On round 1, take 2 damage. You have 13 - 2 = 11 health.
On round 2, take 7 damage. You have 11 - 7 = 4 health.
On round 3, use your armor to protect you from 4 damage. You have 4 - 0 = 4 health.
On round 4, take 3 damage. You have 4 - 3 = 1 health.
Note that 13 is the minimum health you need to start with to beat the game.

Example 2:

Input: damage = [2,5,3,4], armor = 7
Output: 10
Explanation: One optimal way to beat the game starting at 10 health is:
On round 1, take 2 damage. You have 10 - 2 = 8 health.
On round 2, use your armor to protect you from 5 damage. You have 8 - 0 = 8 health.
On round 3, take 3 damage. You have 8 - 3 = 5 health.
On round 4, take 4 damage. You have 5 - 4 = 1 health.
Note that 10 is the minimum health you need to start with to beat the game.

Example 3:

Input: damage = [3,3,3], armor = 0
Output: 10
Explanation: One optimal way to beat the game starting at 10 health is:
On round 1, take 3 damage. You have 10 - 3 = 7 health.
On round 2, take 3 damage. You have 7 - 3 = 4 health.
On round 3, take 3 damage. You have 4 - 3 = 1 health.
Note that you did not use your armor ability.

 

Constraints:

  • n == damage.length
  • 1 <= n <= 105
  • 0 <= damage[i] <= 105
  • 0 <= armor <= 105

Solutions

Solution 1: Greedy

Thinking

Damage is taken in order and health must stay positive after every round. Armor may be used once, replacing that round's damage with \(\max(0, d-\textit{armor})\). Trying every round is \(O(n)\) and would pass, but the choice collapses to one comparison.

Without armor the needed health is the total damage plus one. Armor never blocks more than its own value or the damage of the chosen round, so the saving is \(\min(\max(\textit{damage}), \textit{armor})\). Apply it on the heaviest hit.

We can greedily choose to use the armor skill in the round with the highest damage. Suppose the maximum damage is \(\textit{mx}\), then we can avoid \(\min(\textit{mx}, \textit{armor})\) damage. Therefore, the minimum health required is \(\sum(\textit{damage}) - \min(\textit{mx}, \textit{armor}) + 1\).

The time complexity is \(O(n)\), where \(n\) is the length of the array \(\textit{damage}\). The space complexity is \(O(1)\).

1
2
3
class Solution:
    def minimumHealth(self, damage: List[int], armor: int) -> int:
        return sum(damage) - min(max(damage), armor) + 1
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
class Solution {
    public long minimumHealth(int[] damage, int armor) {
        long s = 0;
        int mx = damage[0];
        for (int v : damage) {
            s += v;
            mx = Math.max(mx, v);
        }
        return s - Math.min(mx, armor) + 1;
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
class Solution {
public:
    long long minimumHealth(vector<int>& damage, int armor) {
        long long s = 0;
        int mx = damage[0];
        for (int& v : damage) {
            s += v;
            mx = max(mx, v);
        }
        return s - min(mx, armor) + 1;
    }
};
1
2
3
4
5
6
7
8
9
func minimumHealth(damage []int, armor int) int64 {
    var s int64
    var mx int
    for _, v := range damage {
        s += int64(v)
        mx = max(mx, v)
    }
    return s - int64(min(mx, armor)) + 1
}
1
2
3
4
5
6
7
8
9
function minimumHealth(damage: number[], armor: number): number {
    let s = 0;
    let mx = 0;
    for (const v of damage) {
        mx = Math.max(mx, v);
        s += v;
    }
    return s - Math.min(mx, armor) + 1;
}

Comments