
Problem Statement
In a fictional battle scenario, n
heroes are pitted against m
monsters. Each hero and monster has an associated power value, and heroes can only defeat monsters with a power less than or equal to their own. The strengths of the heroes and monsters are represented by two separate 1-indexed arrays, heroes
and monsters
, respectively.
Additionally, each monster carries a certain amount of coins, denoted by the 1-indexed coins
array, representing the reward for defeating that monster. The task is to calculate and return an array ans
, where each element ans[i]
signifies the maximum number of coins the i-th
hero can collect by defeating various monsters under the rule that a monster's power must be less than or equal to the hero's power for a successful defeat.
The challenge emphasizes that a hero's ability to collect coins does not diminish with successive battles, allowing them to continue collecting from multiple monsters, as long as the power conditions are met. Furthermore, multiple heroes can defeat the same monster, but each hero can defeat a particular monster just once per battle.
Examples
Example 1
Input:
heroes = [1, 4, 2] monsters = [1, 1, 5, 2, 3] coins = [2, 3, 4, 5, 6]
Output:
[5, 16, 10]
Explanation:
1st hero can defeat monsters at indices [0,1]: 2 + 3 = 5 2nd hero can defeat monsters at [0,1,3,4]: 2 + 3 + 5 + 6 = 16 3rd hero can defeat monsters at [0,1,3]: 2 + 3 + 5 = 10
Example 2
Input:
heroes = [5] monsters = [2, 3, 1, 2] coins = [10, 6, 5, 2]
Output:
[23]
Explanation:
The hero can defeat all monsters. Total coins = 10 + 6 + 5 + 2 = 23
Example 3
Input:
heroes = [4, 4] monsters = [5, 7, 8] coins = [1, 1, 1]
Output:
[0, 0]
Explanation:
No hero can defeat any monster, so the answer is [0, 0]
Constraints
1 <= n == heroes.length <= 10^5
1 <= m == monsters.length <= 10^5
coins.length == m
1 <= heroes[i], monsters[i], coins[i] <= 10^9
Approach and Intuition
To solve this efficiently:
Preprocessing:
- Combine
monsters[i]
andcoins[i]
into pairs and sort them bymonsters[i]
.
- Combine
Prefix Sum Construction:
- Create a prefix sum of coins, such that for any power threshold, we can quickly find the total coin sum for all monsters up to that power using binary search.
Binary Search for Efficiency:
- For each hero, use binary search to find the rightmost monster the hero can defeat (i.e., monster power ≤ hero power).
- The corresponding prefix sum gives the total coins collectible by that hero.
Time Complexity:
- Sorting monsters and coins: O(m log m)
- Processing each hero: O(n log m) using binary search
- Total: O((n + m) log m)
This strategy ensures efficient computation even for the upper bound of constraints.
Solutions
- C++
- Java
- Python
class Solution {
public:
vector<long long> collectMaxCoins(vector<int>& heroes, vector<int>& monsters, vector<int>& coins) {
vector<long long> result(heroes.size());
vector<pair<int, int>> pairedMonsters(monsters.size());
for (int i = 0; i < monsters.size(); i++) {
pairedMonsters[i] = make_pair(monsters[i], coins[i]);
}
// Sorting monsters and coins together by monster strength
sort(pairedMonsters.begin(), pairedMonsters.end());
vector<long long> accumulatedCoins(coins.size());
long long cumulativeSum = 0;
for (int i = 0; i < pairedMonsters.size(); i++) {
cumulativeSum += pairedMonsters[i].second;
accumulatedCoins[i] = cumulativeSum;
}
for (int i = 0; i < heroes.size(); i++) {
result[i] = calculateMaximumCoins(pairedMonsters, heroes[i], accumulatedCoins);
}
return result;
}
private:
long long calculateMaximumCoins(const vector<pair<int, int>>& pairedMonsters,
int heroStrength, const vector<long long>& accumulatedCoins) {
int left = 0;
int right = pairedMonsters.size() - 1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (pairedMonsters[mid].first > heroStrength)
right = mid - 1;
else
left = mid + 1;
}
if (left == 0 && pairedMonsters[left].first > heroStrength) {
return 0; // no monsters can be defeated
}
return accumulatedCoins[right];
}
};
This solution outlines an approach to finding out the maximum number of coins that heroes can collect by defeating monsters, as determined by their respective strengths. The solution employs the C++ programming language, utilizing standard library features such as vectors and pairs.
Implementation Details:
Hero and Monster Modeling:
- Two sets of vectors are used—one to represent the heroes' strengths and another to represent monsters with associated coins, modeled as pairs.
Sorting Monsters:
- Create pairs from monsters and their respective coin values. These pairs are sorted based on the monster's strength, ensuring that heroes can potentially maximize coin collection by defeating weaker monsters first.
Coin Accumulation Calculation:
- Compute a prefix sum for the coins that reflects the total coins achievable from defeating a sequence of the weakest monsters up to each position in the sorted list.
Main Calculation Loop:
- For each hero, determine how many monsters they can defeat based on their strength using a binary search mechanism. The binary search in the
calculateMaximumCoins
function finds the upper bound of monster's strength a hero can defeat and uses this position to index into the precomputed prefix sum array to find the maximum coins collectible.
- For each hero, determine how many monsters they can defeat based on their strength using a binary search mechanism. The binary search in the
Binary Search Mechanism:
- Adjust the search space based on the comparison between hero's strength and the monster's strength at the midpoint. This iteratively narrows down the section of the array, which directly corresponds to the range of monsters a hero can potentially defeat.
Edge Case Handling:
- Consider scenarios where no monsters can be defeated if all are stronger than the hero by checking the strength of the weakest monster against the hero's strength.
Output Details:
- The result is a vector where each entry corresponds to the maximum coins that can be collected by each hero based on their strength against the sorted list of monsters.
This method provides an efficient and logical approach to allocating resources (heroes) against challenges (monsters) while maximizing rewards (coins). The use of sorting, paired data structuring, and binary search ensures that the solution remains computationally feasible even for larger numbers of heroes or monsters.
class Solution {
public long[] maxCoins(int[] warriors, int[] beasts, int[] treasures) {
long[] result = new long[warriors.length];
int[][] beastAndTreasure = new int[beasts.length][2];
for (int i = 0; i < beasts.length; i++) {
beastAndTreasure[i][0] = beasts[i];
beastAndTreasure[i][1] = treasures[i];
}
// sort beasts by their strength
Arrays.sort(beastAndTreasure, (a, b) -> Integer.compare(a[0], b[0]));
long[] cumulativeTreasures = new long[treasures.length];
long accumulatedTreasures = 0;
for (int i = 0; i < beastAndTreasure.length; i++) {
accumulatedTreasures += beastAndTreasure[i][1];
cumulativeTreasures[i] = accumulatedTreasures;
}
for (int i = 0; i < warriors.length; i++) {
int warriorStrength = warriors[i];
result[i] = sumCoins(beastAndTreasure, warriorStrength, cumulativeTreasures);
}
return result;
}
private long sumCoins(int[][] beastAndTreasure, int warriorStrength, long[] cumulativeTreasures) {
int left = 0;
int right = beastAndTreasure.length - 1;
while (left <= right) {
int mid = (left + right) / 2;
if (beastAndTreasure[mid][0] > warriorStrength) {
right = mid - 1;
} else {
left = mid + 1;
}
}
return left == 0 && beastAndTreasure[0][0] > warriorStrength ? 0 : cumulativeTreasures[right];
}
}
The given Java solution addresses the problem of calculating the maximum coins a group of heroes (warriors) can collect when they face various beasts, each possessing a certain number of coins. The program defines a method that returns an array of long integers, representing the maximum coins each warrior can collect, given their strength.
Start by creating an array to store the result. Each index will correspond to a warrior and will store the total coins that warrior can collect.
Combine each beast's strength and the corresponding treasure it holds into one array,
beastAndTreasure
, for more efficient processing.Sort the
beastAndTreasure
array based on beasts' strengths using a custom comparator. This ensures that the warriors can be processed against beasts in increasing order of strength.Calculate cumulative treasures which is a running total of treasures up to each beast, stored in
cumulativeTreasures
. This array helps in quickly calculating the total coins a warrior can collect when defeating multiple beasts up to a certain strength level in order.For each warrior, calculate the total coins they can collect using a helper function
sumCoins
.- This function performs a binary search on the
beastAndTreasure
array to find out up to which beast the current warrior's strength can potentially defeat. - It then returns the amount of treasure collectable from all those beasts using the
cumulativeTreasures
.
- This function performs a binary search on the
Return the result array to conclude the processing.
This implementation efficiently calculates the maximum coins each warrior can collect by harnessing binary search and cumulative sums, minimizing the need to repeatedly sum treasures for each warrior.
class Solution:
def maxCoins(self, hero_list, monster_list, coin_list):
result = [0] * len(hero_list)
monster_coin_combination = sorted(zip(monster_list, coin_list), key=lambda x: x[0])
accumulated_coins = [0] * len(coin_list)
temp_sum = 0
for index, (_, coin) in enumerate(monster_coin_combination):
temp_sum += coin
accumulated_coins[index] = temp_sum
for index, hero in enumerate(hero_list):
result[index] = self.calculateTotalCoins(monster_coin_combination, hero, accumulated_coins)
return result
def calculateTotalCoins(self, monster_coin_combination, hero_strength, accumulated_coins):
left, right = 0, len(monster_coin_combination) - 1
while left <= right:
mid = left + (right - left) // 2
if monster_coin_combination[mid][0] > hero_strength:
right = mid - 1
else:
left = mid + 1
if left == 0 and monster_coin_combination[left][0] > hero_strength:
return 0
return accumulated_coins[right]
The provided Python code defines a solution for calculating the maximum coins that heroes can collect when facing a series of monsters with varying strengths and coin values. Each hero has a certain strength and can only defeat monsters that have a strength less than or equal to their own.
The input lists
hero_list
,monster_list
, andcoin_list
represent the strengths of the heroes, the strengths of the monsters, and the coins each monster possesses, respectively.The function
maxCoins
initializes the results array to store the coins collected by each hero. It combines and sorts themonster_list
andcoin_list
to ascertain the total coins available up to each monster, if all preceding monsters (including the current one) are defeated.It then calculates the total coins a hero can collect using a helper function
calculateTotalCoins
, which performs a binary search to determine how many monsters a particular hero can defeat based on the hero's strength. This function considers the cumulative coins obtained by defeating monsters up to the strongest monster a hero can defeat.The behavior of the binary search within
calculateTotalCoins
ensures that heroes are matched with the maximum index of the monster they can defeat, to maximize the coin collection. Edge cases where a hero cannot defeat any monsters are appropriately handled by checking if the first monster in the sorted list is too strong for the hero.Finally,
maxCoins
returns a list of total coins that each hero can collect.
This solution efficiently pairs heroes with monsters they can defeat using sorting and binary search, ensuring optimal performance even with large lists of heroes and monsters.
No comments yet.