📌  相关文章
📜  查找可以通过从数组中删除元素获得的最大点数(1)

📅  最后修改于: 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 的子序列,以及删除这个数之后能获得的点数。点数的计算可以分别从两个方面来考虑:

  1. 如果删除的数是奇数位的数字,如果它左右两边都存在数字,那么就可以获得其周围两个数字中较小的那个。
  2. 如果删除的数是偶数位的数字,如果它周围有其他的数字,那么就可以获得其左右两侧数字的和。

因此,我们需要记录一个 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]

代码片段:请注意将注释和代码区分开来,不要加注释。