开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第9天,点击查看活动详情
从栈中取出 K 个硬币的最大面值和
一张桌子上总共有 n 个硬币 栈 。每个栈有 正整数 个带面值的硬币。
每一次操作中,你可以从任意一个栈的 顶部 取出 1 个硬币,从栈中移除它,并放入你的钱包里。
给你一个列表 piles ,其中 piles[i] 是一个整数数组,分别表示第 i 个栈里 从顶到底 的硬币面值。同时给你一个正整数 k ,请你返回在 恰好 进行 k 次操作的前提下,你钱包里硬币面值之和 最大为多少 。
示例1:
输入:piles = [[1,100,3],[7,8,9]], k = 2
输出:101
解释:
上图展示了几种选择 k 个硬币的不同方法。
我们可以得到的最大面值为 101 。
示例2:
输入:piles = [[100],[100],[100],[100],[100],[100],[1,1,1,1,1,1,700]], k = 7
输出:706
解释:
如果我们所有硬币都从最后一个栈中取,可以得到最大面值和。
提示:
- n == piles.length
- 1 <= n <= 1000
- 1 <= piles[i][j] <= 105
- 1 <= k <= sum(piles[i].length) <= 2000
解题思路:
记忆化搜索 dfs(i, c) 表示从索引为 idx 的栈开始取,还可以取 c 次的最大和
我的答案:
/**
* @param {number[][]} piles
* @param {number} k
* @return {number}
*/
var maxValueOfCoins = function(piles, k) {
const m = piles.length;
const preSum = new Array(m).fill(0).map(() => []);
for (let i = 0; i < m; i++) {
let sum = 0;
preSum[i].push(0);
for (let j = 0; j < piles[i].length; j++) {
sum += piles[i][j];
preSum[i].push(sum);
}
}
const dfs = (i, c, memo) => {
if (i >= m || c <= 0) {
return 0;
}
if (memo[i][c] !== -1) {
return memo[i][c];
}
let max = -Infinity;
for (let j = 0; j <= Math.min(piles[i].length, c); j++) {
max = Math.max(
max,
preSum[i][j] + dfs(i + 1, c - j, memo)
);
}
memo[i][c] = max;
return memo[i][c];
}
return dfs(0, k, new Array(m).fill(0).map(() => new Array(k + 1).fill(-1)));
};
最后
如果有更好的解法或者思路, 欢迎在评论区和我交流~ ღ( ´・ᴗ・` )