In a mystic dungeon, n
magicians are standing in a line. Each magician has an attribute that gives you energy. Some magicians can give you negative energy, which means taking energy from you.
You have been cursed in such a way that after absorbing energy from magician i
, you will be instantly transported to magician (i + k)
. This process will be repeated until you reach the magician where (i + k)
does not exist.
In other words, you will choose a starting point and then teleport with k
jumps until you reach the end of the magicians' sequence, absorbing all the energy during the journey.
You are given an array energy
and an integer k
. Return the maximum possible energy you can gain.
Note that when you are reach a magician, you must take energy from them, whether it is negative or positive energy.
Example 1:
Input: energy = [5,2,-10,-5,1], k = 3
Output: 3
Explanation: We can gain a total energy of 3 by starting from magician 1 absorbing 2 + 1 = 3.
Example 2:
Input: energy = [-2,-3,-1], k = 2
Output: -1
Explanation: We can gain a total energy of -1 by starting from magician 2.
Constraints:
1 <= energy.length <= 105
-1000 <= energy[i] <= 1000
1 <= k <= energy.length - 1
When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
The brute force approach to finding the maximum energy you can get from the mystic dungeon involves exploring every possible path. You try going through all possible room combinations, figuring out the energy you get from each. Then you simply pick the path that gives you the most energy.
Here's how the algorithm would work step-by-step:
def find_maximum_energy_brute_force(dungeon):
maximum_energy_found = 0
def explore_dungeon(current_room_index, current_energy):
nonlocal maximum_energy_found
# Add the energy from the current room to the total
current_energy += dungeon[current_room_index]
# If we're at the end, update the maximum energy
if current_room_index == len(dungeon) - 1:
maximum_energy_found = max(maximum_energy_found, current_energy)
return
# Explore all possible next rooms
for next_room_index in range(current_room_index + 1, len(dungeon)):
# Recursively explore from the next room
explore_dungeon(next_room_index, current_energy)
# Start exploring from the first room
explore_dungeon(0, 0)
return maximum_energy_found
The best way to find the maximum energy is to figure out the best path through the dungeon one step at a time. We will use past choices to help make future decisions so we can always make the best move to gain the most energy.
Here's how the algorithm would work step-by-step:
def max_energy(dungeon):
rows = len(dungeon)
cols = len(dungeon[0])
energy_collected = [[0] * cols for _ in range(rows)]
path_taken = [[''] * cols for _ in range(rows)]
energy_collected[0][0] = dungeon[0][0]
for col_index in range(1, cols):
energy_collected[0][col_index] = energy_collected[0][col_index - 1] + dungeon[0][col_index]
path_taken[0][col_index] = 'R'
for row_index in range(1, rows):
energy_collected[row_index][0] = energy_collected[row_index - 1][0] + dungeon[row_index][0]
path_taken[row_index][0] = 'D'
for row_index in range(1, rows):
for col_index in range(1, cols):
# Determine the optimal path (down or right).
if energy_collected[row_index - 1][col_index] > energy_collected[row_index][col_index - 1]:
energy_collected[row_index][col_index] = energy_collected[row_index - 1][col_index] + dungeon[row_index][col_index]
path_taken[row_index][col_index] = 'D'
else:
energy_collected[row_index][col_index] = energy_collected[row_index][col_index - 1] + dungeon[row_index][col_index]
path_taken[row_index][col_index] = 'R'
optimal_path = ''
row_index = rows - 1
col_index = cols - 1
# Trace back to construct the optimal path.
while row_index > 0 or col_index > 0:
if path_taken[row_index][col_index] == 'D':
optimal_path = 'D' + optimal_path
row_index -= 1
else:
optimal_path = 'R' + optimal_path
col_index -= 1
return energy_collected[rows - 1][cols - 1], optimal_path
Case | How to Handle |
---|---|
Null or empty dungeon array | Return 0 immediately, as there's no energy to collect. |
Dungeon array with a single room (one element) | Return the value of the single room as the maximum energy. |
Dungeon array with only negative energy rooms | Return the least negative (largest) value to minimize energy loss. |
Dungeon array with all zero energy rooms | Return 0 as the maximum energy that can be collected. |
Large dungeon array (performance scaling) | Ensure the algorithm used has a time complexity that scales reasonably, like O(n) or O(n log n). |
Integer overflow in energy calculation | Use a data type that can accommodate large energy values (e.g., long long in C++, long in Java, or arbitrary precision integers in Python). |
Dungeon array with extreme positive and negative values | The solution must handle potentially large differences between room values to avoid incorrect maximum energy calculations. |
Array containing duplicate energy values | The algorithm should correctly consider all paths regardless of duplicate energy amounts available in different rooms. |