📜  最大总和增加子序列| DP-14(1)

📅  最后修改于: 2023-12-03 15:26:25.919000             🧑  作者: Mango

最大总和增加子序列

最大总和增加子序列(Maximum Sum Increasing Subsequence)是一个常见的动态规划问题,其要求是从一个无序的整数序列中,找到一个子序列,使得该子序列的数值之和最大、且子序列中的数值按顺序递增。

例如,对于序列 [1, 101, 2, 3, 100, 4, 5],最大总和增加子序列为 [1, 2, 3, 100],其数值之和为 106。

动态规划解法

动态规划是解决最大总和增加子序列问题的常用方法。具体步骤如下:

  1. 定义状态:定义 dp[i] 表示以第 i 个元素为结尾的最大总和增加子序列的数值之和。
  2. 状态转移:对于第 i 个元素,寻找在其之前的所有元素中,数值小于当前元素的子序列,并从中选择数值之和最大的子序列,然后将当前元素添加到该子序列的末尾,即可得到以当前元素为结尾的最大总和增加子序列。具体而言,可以从 dp[0] ~ dp[i-1] 中,找到最大的 dp[j],使得 nums[j] < nums[i],然后令 dp[i] = dp[j] + nums[i]。此外,需要注意的是,如果不存在这样的 dp[j],则 dp[i] 只能是 nums[i] 自身。
  3. 最终结果:遍历 dp 数组,找到其中数值最大的元素,即为给定序列的最大总和增加子序列的数值之和。

以下是对应的 Python 代码实现:

def max_sum_increasing_subsequence(nums):
    n = len(nums)
    dp = nums[:]
    for i in range(1, n):
        for j in range(i):
            if nums[j] < nums[i]:
                dp[i] = max(dp[i], dp[j] + nums[i])
    return max(dp)

nums = [1, 101, 2, 3, 100, 4, 5]
print(max_sum_increasing_subsequence(nums)) # 输出 106
时间复杂度

上述算法的时间复杂度为 $O(n^2)$,其中 $n$ 是序列的长度。具体地,遍历整个序列需要 $O(n)$ 的时间,而对于每个元素,需要遍历其之前的所有元素,这一步的时间复杂度为 $O(n)$。因此,总时间复杂度为 $O(n^2)$。

空间复杂度

上述算法需要使用一个长度为 $n$ 的数组 dp 来存储以每个元素结尾的最大总和增加子序列的数值之和,因此其空间复杂度为 $O(n)$。

参考文献
  • CLRS. Introduction to Algorithms, 3rd edition. Chapter 15. Dynamic Programming.