Skip to content

feat: add solutions to lc problem: No.2218 #3975

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jan 21, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
243 changes: 179 additions & 64 deletions solution/2200-2299/2218.Maximum Value of K Coins From Piles/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,15 +66,21 @@ tags:

<!-- solution:start -->

### 方法一:动态规划
### 方法一:动态规划(分组背包)

对每个栈求前缀和 $s$,$s_i$ 视为一个体积为 $i$ 且价值为 $s_i$ 的物品
我们定义 $f[i][j]$ 表示从前 $i$ 组中取出 $j$ 个硬币的最大面值和,那么答案为 $f[n][k]$,其中 $n$ 为栈的数量

问题转化为求从 $n$ 个物品组中取物品体积为 $k$,且每组最多取一个物品时的最大价值和
对于第 $i$ 组,我们可以选择取前 $0$, $1$, $2$, $\cdots$, $k$ 个硬币。我们可以通过前缀和数组 $s$ 来快速计算出取前 $h$ 个硬币的面值和

定义 $dp[i][j]$ 表示从前 $i$ 个组中取体积之和为 $j$ 的物品时的最大价值和。
状态转移方程为:

枚举第 $i$ 组所有物品,设当前物品体积为 $w$,价值为 $v$,则有 $f[i][j]=max(f[i][j],f[i-1][j-w]+v)$。
$$
f[i][j] = \max(f[i][j], f[i - 1][j - h] + s[h])
$$

其中 $0 \leq h \leq j$,而 $s[h]$ 表示第 $i$ 组中取前 $h$ 个硬币的面值和。

时间复杂度 $O(k \times L)$,空间复杂度 $O(n \times k)$。其中 $L$ 为所有硬币的数量,而 $n$ 为栈的数量。

<!-- tabs:start -->

Expand All @@ -83,15 +89,16 @@ tags:
```python
class Solution:
def maxValueOfCoins(self, piles: List[List[int]], k: int) -> int:
presum = [list(accumulate(p, initial=0)) for p in piles]
n = len(piles)
dp = [[0] * (k + 1) for _ in range(n + 1)]
for i, s in enumerate(presum, 1):
f = [[0] * (k + 1) for _ in range(n + 1)]
for i, nums in enumerate(piles, 1):
s = list(accumulate(nums, initial=0))
for j in range(k + 1):
for idx, v in enumerate(s):
if j >= idx:
dp[i][j] = max(dp[i][j], dp[i - 1][j - idx] + v)
return dp[-1][-1]
for h, w in enumerate(s):
if j < h:
break
f[i][j] = max(f[i][j], f[i - 1][j - h] + w)
return f[n][k]
```

#### Java
Expand All @@ -100,26 +107,21 @@ class Solution:
class Solution {
public int maxValueOfCoins(List<List<Integer>> piles, int k) {
int n = piles.size();
List<int[]> presum = new ArrayList<>();
for (List<Integer> p : piles) {
int m = p.size();
int[] s = new int[m + 1];
for (int i = 0; i < m; ++i) {
s[i + 1] = s[i] + p.get(i);
int[][] f = new int[n + 1][k + 1];
for (int i = 1; i <= n; i++) {
List<Integer> nums = piles.get(i - 1);
int[] s = new int[nums.size() + 1];
s[0] = 0;
for (int j = 1; j <= nums.size(); j++) {
s[j] = s[j - 1] + nums.get(j - 1);
}
presum.add(s);
}
int[] dp = new int[k + 1];
for (int[] s : presum) {
for (int j = k; j >= 0; --j) {
for (int idx = 0; idx < s.length; ++idx) {
if (j >= idx) {
dp[j] = Math.max(dp[j], dp[j - idx] + s[idx]);
}
for (int j = 0; j <= k; j++) {
for (int h = 0; h < s.length && h <= j; h++) {
f[i][j] = Math.max(f[i][j], f[i - 1][j - h] + s[h]);
}
}
}
return dp[k];
return f[n][k];
}
}
```
Expand All @@ -130,22 +132,21 @@ class Solution {
class Solution {
public:
int maxValueOfCoins(vector<vector<int>>& piles, int k) {
vector<vector<int>> presum;
for (auto& p : piles) {
int m = p.size();
vector<int> s(m + 1);
for (int i = 0; i < m; ++i) s[i + 1] = s[i] + p[i];
presum.push_back(s);
}
vector<int> dp(k + 1);
for (auto& s : presum) {
for (int j = k; ~j; --j) {
for (int idx = 0; idx < s.size(); ++idx) {
if (j >= idx) dp[j] = max(dp[j], dp[j - idx] + s[idx]);
int n = piles.size();
vector<vector<int>> f(n + 1, vector<int>(k + 1));
for (int i = 1; i <= n; i++) {
vector<int> nums = piles[i - 1];
vector<int> s(nums.size() + 1);
for (int j = 1; j <= nums.size(); j++) {
s[j] = s[j - 1] + nums[j - 1];
}
for (int j = 0; j <= k; j++) {
for (int h = 0; h < s.size() && h <= j; h++) {
f[i][j] = max(f[i][j], f[i - 1][j - h] + s[h]);
}
}
}
return dp[k];
return f[n][k];
}
};
```
Expand All @@ -154,26 +155,50 @@ public:

```go
func maxValueOfCoins(piles [][]int, k int) int {
var presum [][]int
for _, p := range piles {
m := len(p)
s := make([]int, m+1)
for i, v := range p {
s[i+1] = s[i] + v
}
presum = append(presum, s)
n := len(piles)
f := make([][]int, n+1)
for i := range f {
f[i] = make([]int, k+1)
}
dp := make([]int, k+1)
for _, s := range presum {
for j := k; j >= 0; j-- {
for idx, v := range s {
if j >= idx {
dp[j] = max(dp[j], dp[j-idx]+v)
for i := 1; i <= n; i++ {
nums := piles[i-1]
s := make([]int, len(nums)+1)
for j := 1; j <= len(nums); j++ {
s[j] = s[j-1] + nums[j-1]
}

for j := 0; j <= k; j++ {
for h, w := range s {
if j < h {
break
}
f[i][j] = max(f[i][j], f[i-1][j-h]+w)
}
}
}
return dp[k]
return f[n][k]
}
```

#### TypeScript

```ts
function maxValueOfCoins(piles: number[][], k: number): number {
const n = piles.length;
const f: number[][] = Array.from({ length: n + 1 }, () => Array(k + 1).fill(0));
for (let i = 1; i <= n; i++) {
const nums = piles[i - 1];
const s = Array(nums.length + 1).fill(0);
for (let j = 1; j <= nums.length; j++) {
s[j] = s[j - 1] + nums[j - 1];
}
for (let j = 0; j <= k; j++) {
for (let h = 0; h < s.length && h <= j; h++) {
f[i][j] = Math.max(f[i][j], f[i - 1][j - h] + s[h]);
}
}
}
return f[n][k];
}
```

Expand All @@ -183,7 +208,11 @@ func maxValueOfCoins(piles [][]int, k int) int {

<!-- solution:start -->

### 方法二
### 方法二:动态规划(空间优化)

我们可以发现,对于第 $i$ 组,我们只需要用到 $f[i - 1][j]$ 和 $f[i][j - h]$,因此我们可以将二维数组优化为一维数组。

时间复杂度 $O(k \times L)$,空间复杂度 $O(k)$。

<!-- tabs:start -->

Expand All @@ -192,14 +221,100 @@ func maxValueOfCoins(piles [][]int, k int) int {
```python
class Solution:
def maxValueOfCoins(self, piles: List[List[int]], k: int) -> int:
presum = [list(accumulate(p, initial=0)) for p in piles]
dp = [0] * (k + 1)
for s in presum:
f = [0] * (k + 1)
for nums in piles:
s = list(accumulate(nums, initial=0))
for j in range(k, -1, -1):
for idx, v in enumerate(s):
if j >= idx:
dp[j] = max(dp[j], dp[j - idx] + v)
return dp[-1]
for h, w in enumerate(s):
if j < h:
break
f[j] = max(f[j], f[j - h] + w)
return f[k]
```

#### Java

```java
class Solution {
public int maxValueOfCoins(List<List<Integer>> piles, int k) {
int[] f = new int[k + 1];
for (var nums : piles) {
int[] s = new int[nums.size() + 1];
for (int j = 1; j <= nums.size(); ++j) {
s[j] = s[j - 1] + nums.get(j - 1);
}
for (int j = k; j >= 0; --j) {
for (int h = 0; h < s.length && h <= j; ++h) {
f[j] = Math.max(f[j], f[j - h] + s[h]);
}
}
}
return f[k];
}
}
```

#### C++

```cpp
class Solution {
public:
int maxValueOfCoins(vector<vector<int>>& piles, int k) {
vector<int> f(k + 1);
for (auto& nums : piles) {
vector<int> s(nums.size() + 1);
for (int j = 1; j <= nums.size(); ++j) {
s[j] = s[j - 1] + nums[j - 1];
}
for (int j = k; j >= 0; --j) {
for (int h = 0; h < s.size() && h <= j; ++h) {
f[j] = max(f[j], f[j - h] + s[h]);
}
}
}
return f[k];
}
};
```

#### Go

```go
func maxValueOfCoins(piles [][]int, k int) int {
f := make([]int, k+1)
for _, nums := range piles {
s := make([]int, len(nums)+1)
for j := 1; j <= len(nums); j++ {
s[j] = s[j-1] + nums[j-1]
}
for j := k; j >= 0; j-- {
for h := 0; h < len(s) && h <= j; h++ {
f[j] = max(f[j], f[j-h]+s[h])
}
}
}
return f[k]
}
```

#### TypeScript

```ts
function maxValueOfCoins(piles: number[][], k: number): number {
const f: number[] = Array(k + 1).fill(0);
for (const nums of piles) {
const s: number[] = Array(nums.length + 1).fill(0);
for (let j = 1; j <= nums.length; j++) {
s[j] = s[j - 1] + nums[j - 1];
}
for (let j = k; j >= 0; j--) {
for (let h = 0; h < s.length && h <= j; h++) {
f[j] = Math.max(f[j], f[j - h] + s[h]);
}
}
}
return f[k];
}
```

<!-- tabs:end -->
Expand Down
Loading
Loading