LeetCode 2403. Minimum Time to Kill All Monsters Solution in Java, C++, Python & More | Explanation + Code

CoderIndeed
0
2403. Minimum Time to Kill All Monsters

Description

You are given an integer array power where power[i] is the power of the ith monster.

You start with 0 mana points, and each day you increase your mana points by gain where gain initially is equal to 1.

Each day, after gaining gain mana, you can defeat a monster if your mana points are greater than or equal to the power of that monster. When you defeat a monster:

  • your mana points will be reset to 0, and
  • the value of gain increases by 1.

Return the minimum number of days needed to defeat all the monsters.

 

Example 1:

Input: power = [3,1,4]
Output: 4
Explanation: The optimal way to beat all the monsters is to:
- Day 1: Gain 1 mana point to get a total of 1 mana point. Spend all mana points to kill the 2nd monster.
- Day 2: Gain 2 mana points to get a total of 2 mana points.
- Day 3: Gain 2 mana points to get a total of 4 mana points. Spend all mana points to kill the 3rd monster.
- Day 4: Gain 3 mana points to get a total of 3 mana points. Spend all mana points to kill the 1st monster.
It can be proven that 4 is the minimum number of days needed. 

Example 2:

Input: power = [1,1,4]
Output: 4
Explanation: The optimal way to beat all the monsters is to:
- Day 1: Gain 1 mana point to get a total of 1 mana point. Spend all mana points to kill the 1st monster.
- Day 2: Gain 2 mana points to get a total of 2 mana points. Spend all mana points to kill the 2nd monster.
- Day 3: Gain 3 mana points to get a total of 3 mana points.
- Day 4: Gain 3 mana points to get a total of 6 mana points. Spend all mana points to kill the 3rd monster.
It can be proven that 4 is the minimum number of days needed. 

Example 3:

Input: power = [1,2,4,9]
Output: 6
Explanation: The optimal way to beat all the monsters is to:
- Day 1: Gain 1 mana point to get a total of 1 mana point. Spend all mana points to kill the 1st monster.
- Day 2: Gain 2 mana points to get a total of 2 mana points. Spend all mana points to kill the 2nd monster.
- Day 3: Gain 3 mana points to get a total of 3 mana points.
- Day 4: Gain 3 mana points to get a total of 6 mana points.
- Day 5: Gain 3 mana points to get a total of 9 mana points. Spend all mana points to kill the 4th monster.
- Day 6: Gain 4 mana points to get a total of 4 mana points. Spend all mana points to kill the 3rd monster.
It can be proven that 6 is the minimum number of days needed.

 

Constraints:

  • 1 <= power.length <= 17
  • 1 <= power[i] <= 109

Solutions

Solution 1: State Compression + Memoization Search

We note that the number of monsters is at most 17, which means we can use a 17-bit binary number to represent the state of the monsters. The i-th bit being 1 indicates that the i-th monster is still alive, and 0 indicates that the i-th monster has been defeated.

We design a function dfs(mask) to represent the minimum number of days needed to defeat all monsters when the current state of the monsters is mask. The answer is dfs(2n - 1), where n is the number of monsters.

The calculation of the function dfs(mask) is as follows:

  • If mask = 0, it means all monsters have been defeated, return 0;
  • Otherwise, we enumerate each monster i. If the i-th monster is still alive, we can choose to defeat the i-th monster, then recursively calculate dfs(mask \oplus 2i), and update the answer to ans = min(ans, dfs(mask \oplus 2i) + \lceil xgain \rceil), where x is the strength of the i-th monster, and gain = 1 + (n - mask.bitcount()) represents the current daily mana gain.

Finally, we return dfs(2n - 1).

The time complexity is O(2n × n), and the space complexity is O(2n). Here, n is the number of monsters.

PythonJavaC++GoTypeScript
class Solution: def minimumTime(self, power: List[int]) -> int: @cache def dfs(mask: int) -> int: if mask == 0: return 0 ans = inf gain = 1 + (n - mask.bit_count()) for i, x in enumerate(power): if mask >> i & 1: ans = min(ans, dfs(mask ^ (1 << i)) + (x + gain - 1) // gain) return ans n = len(power) return dfs((1 << n) - 1)(code-box)

Solution 2: State Compression + Dynamic Programming

We can convert the memoization search in Solution 1 to dynamic programming. Define f[mask] to represent the minimum number of days needed to defeat all monsters when the current state of the monsters is mask. Here, mask is an n-bit binary number, where the i-th bit being 1 indicates that the i-th monster has been defeated, and 0 indicates that the i-th monster is still alive. Initially, f[0] = 0, and the rest f[mask] = +∞. The answer is f[2n - 1].

We enumerate mask in the range [1, 2n - 1]. For each mask, we enumerate each monster i. If the i-th monster is defeated, it can be transferred from the previous state mask \oplus 2i, with a transfer cost of (power[i] + gain - 1) / gain, where gain = mask.bitCount().

Finally, return f[2n - 1].

The time complexity is O(2n × n), and the space complexity is O(2n). Here, n is the number of monsters.

PythonJavaC++GoTypeScript
class Solution: def minimumTime(self, power: List[int]) -> int: n = len(power) f = [inf] * (1 << n) f[0] = 0 for mask in range(1, 1 << n): gain = mask.bit_count() for i, x in enumerate(power): if mask >> i & 1: f[mask] = min(f[mask], f[mask ^ (1 << i)] + (x + gain - 1) // gain) return f[-1](code-box)

Post a Comment

0Comments

Post a Comment (0)

#buttons=(Accept !) #days=(20)

Our website uses cookies to enhance your experience. Check Now
Accept !