📅  最后修改于: 2023-12-03 14:55:33.313000             🧑  作者: Mango
题目:给定一个数组 nums ,你可以对它进行任意次数的两两交换。每次交换 nums[i] 和 nums[j] (i ≠ j),得到一些点数增加的情况。返回所有可行交换方案中,得分最高的方案的得分。
输入:nums = [2,3,4,1,5] 输出:10 解释:可以通过从数组中删除元素获得的最大点数为 10。下面是最优解:
将第 1 个和第 5 个元素交换,得到 nums = [5,3,4,1,2],得分增加 5 。 将第 4 个和第 5 个元素交换,得到 nums = [5,3,4,2,1],得分增加 5 。 总共得到 10 分。
本题是一个典型的动态规划题目。首先我们需要考虑从一个长度为 n 的序列中删除一个数之后得到一个长度为 n-1 的子序列,以及删除这个数之后能获得的点数。点数的计算可以分别从两个方面来考虑:
因此,我们需要记录一个 dp 数组,其中 dp[i][j] 表示在 nums[i:j+1] 的范围内,得到的最大点数。其中我设定 dp[i][j] 表示 nums[i] 到 nums[j] 中删除的数已经被删除。对于每个状态,可以考虑把它划分成两个子问题进行计算。
如果我们不删除 nums[i],那么我们需要寻找子问题 nums[i+1] 到 nums[j] 所获得的最大点数。
如果我们删除 nums[i],那么我们需要寻找子问题 nums[i+2] 到 nums[j] 所获得的最大点数。
如果 nums[i] 和 nums[i+1] 之间的差距比较小,那么我们应该删除 nums[i];否则,我们保留 nums[i+1]。
最终的结果是 dp[0][n-1]
class Solution:
def maximumScore(self, nums: List[int], k: int) -> int:
n = len(nums)
dp = [[0] * n for _ in range(n)]
for l in range(n):
for i in range(n - l):
j = i + l
if i == j:
dp[i][j] = nums[i]
elif i + 1 == j:
dp[i][j] = min(nums[i], nums[j]) * 2
else:
dp[i][j] = max(dp[i + 1][j] + nums[i], dp[i][j - 1] + nums[j])
if i < k < j:
dp[i][j] = max(dp[i][j], dp[i][k - 1] + dp[k + 1][j] + nums[k])
return dp[0][n - 1]
代码片段:请注意将注释和代码区分开来,不要加注释。