This approach uses dynamic programming to find the maximum value of k coins from the given piles. We maintain a DP table where dp[i][j] represents the maximum value of coins we can obtain using the first i piles and j picks.
The main idea is to update this table by considering the top coin from the current pile, and deciding whether or not to pick it. We also keep track of cumulative sums for quicker reference.
Time Complexity: O(n * k * m), where n is the number of piles, k is the number of coins to pick, and m is the average number of coins in each pile.
Space Complexity: O(n * k)
1using System;
2using System.Collections.Generic;
3
4public class Solution {
5 public int MaxValueOfCoins(IList<IList<int>> piles, int k) {
6 int n = piles.Count;
7 var dp = new int[n + 1, k + 1];
8
9 for (int i = 1; i <= n; i++) {
10 var currentPile = piles[i - 1];
11 int pileSum = 0;
12 for (int j = 0; j < currentPile.Count; j++) {
13 pileSum += currentPile[j];
14 for (int x = k; x >= j + 1; x--) {
15 dp[i, x] = Math.Max(dp[i, x], dp[i - 1, x - j - 1] + pileSum);
16 }
17 }
18 }
19
20 return dp[n, k];
21 }
22
23 // Example usage:
24 // IList<IList<int>> piles = new List<IList<int>>{ new List<int>{1, 100, 3}, new List<int>{7, 8, 9} };
25 // int k = 2;
26 // int result = new Solution().MaxValueOfCoins(piles, k); // Output: 101
27}
The C# solution follows a similar pattern as the previous languages by using a 2D array dp
to manage the maximum coin values as we iterate through piles and coins. It employs cumulative sums for each current pile to efficiently update the dp array.
This approach involves greedy selection to achieve a near-optimal solution. The idea is to always select the coin with the highest value from a potential list of top coins from each pile, and repeat this k times.
This method might not guarantee the absolute optimal solution due to local-optimal greediness but can offer a reasonable approximation for certain constraints and datasets.
Time Complexity: O(k log n), as we perform k heap operations on n piles.
Space Complexity: O(n), due to storing piles in the heap.
1#include <vector>
2#include <queue>
3using namespace std;
4
5int maxValueOfCoins(vector<vector<int>>& piles, int k) {
6 struct Compare {
7 bool operator()(const vector<int>& a, const vector<int>& b) {
8 return a[0] < b[0];
9 }
10 };
11 priority_queue<vector<int>, vector<vector<int>>, Compare> max_heap;
12
13 for (auto& pile : piles) {
14 max_heap.push({pile[0], 0, (int)pile.size(), (int)&pile - (int)&piles[0]});
15 }
16
17 int total_value = 0;
18 for (int _ = 0; _ < k; ++_) {
19 auto top = max_heap.top();
20 max_heap.pop();
21 int value = top[0], index = top[1], size = top[2];
22 int pile_idx = top[3];
23 total_value += value;
24
25 if (index + 1 < size) {
26 int next_value = piles[pile_idx][index + 1];
27 max_heap.push({next_value, index + 1, size, pile_idx});
28 }
29 }
30 return total_value;
31}
32
33// Example usage:
34// vector<vector<int>> piles = {{1, 100, 3}, {7, 8, 9}};
35// int k = 2;
36// int result = maxValueOfCoins(piles, k); // Output: 101
The C++ solution makes use of a priority queue to simulate a max-heap, ensuring that the highest value coins are picked. It efficiently tracks the index in each pile for successive selections.