Maximum Coins Heroes Can Collect

Updated on 05 June, 2025
Maximum Coins Heroes Can Collect header image

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:

  1. Preprocessing:

    • Combine monsters[i] and coins[i] into pairs and sort them by monsters[i].
  2. 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.
  3. 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.
  4. 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
cpp
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.
  • 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.

java
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.
  • 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.

python
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, and coin_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 the monster_list and coin_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.

Comments

No comments yet.