返回

Python轻松搞定leetcode 2218:从一堆硬币中获取最大价值

后端

周赛第 286 场的第四题,难度 Hard,以「从一堆硬币中获取最大价值」为题,考察了动态规划和前缀和的思想。题目将实际场景与算法相结合,非常有趣。

首先,我们来看一下题目的具体内容:

给你一个下标从 0 开始的整数数组 piles,其中 piles[i] 表示第 i 堆硬币的数目。你可以从任意一堆硬币中取走任意数目的硬币,也可以不取。

每次操作时,你只能从当前正在考虑的堆中取走硬币。

你需要将取走硬币的操作序列以列表的形式返回。当且仅当你能够取走所有硬币时,才返回列表。如果有多种方法可以取走所有硬币,返回其中任意一种即可。

让我们从一个简单的例子开始, piles = [4, 3, 2, 1, 1]。

我们可以先从第一堆(下标为 0)取走 2 个硬币,然后从第二堆(下标为 1)取走 2 个硬币,再从第三堆(下标为 2)取走 1 个硬币,最后从第四堆(下标为 3)和第五堆(下标为 4)各取走 1 个硬币。这样,我们就取走了所有硬币,并返回取走硬币的操作序列 [2, 2, 1, 1, 1]。

现在,让我们来看看如何使用Python来解决这道难题:

def maxValueOfCoins(piles, k):
    """
    :type piles: List[int]
    :type k: int
    :rtype: List[int]
    """
    # 计算前缀和
    prefix_sum = [0]
    for pile in piles:
        prefix_sum.append(prefix_sum[-1] + pile)

    # 初始化dp数组
    dp = [[-1] * (k + 1) for _ in range(len(piles) + 1)]

    # 填充dp数组
    for i in range(1, len(piles) + 1):
        for j in range(1, k + 1):
            for x in range(1, min(i, j) + 1):
                dp[i][j] = max(dp[i][j], dp[i - x][j - x] + prefix_sum[i] - prefix_sum[i - x])

    # 构建取硬币操作序列
    res = []
    i, j = len(piles), k
    while i > 0 and j > 0:
        for x in range(1, min(i, j) + 1):
            if dp[i][j] == dp[i - x][j - x] + prefix_sum[i] - prefix_sum[i - x]:
                res.append(x)
                i -= x
                j -= x
                break

    return res

这段Python代码首先计算前缀和,然后初始化dp数组。之后,它使用循环填充dp数组,记录取走不同数量的硬币时所能获得的最大价值。最后,它构建取硬币操作序列,并返回。

使用上面的代码,我们可以轻松解决leetcode 2218:从一堆硬币中获取最大价值这道难题。赶快尝试一下吧!