📅  最后修改于: 2023-12-03 15:09:55.376000             🧑  作者: Mango
指定一个整数K,找到一个最长的递增子序列,使其总和值不超过K。
使用动态规划(DP)的思路进行求解,使用一个一维的数组dp
来保存对于0~i这i个数的最长递增子序列的长度,同时,使用一个sum
来记录当前最长递增子序列的和值,当sum
超过K时,需要缩短当前最长递增子序列的长度。
具体流程如下:
n
的数组dp
,全部赋值为1。这里的n
指的是题目给出的序列的长度。sum
为0。i
,都从0到i-1遍历之前的所有位置j
。如果nums[i] > nums[j]
并且dp[j] + 1 > dp[i]
,则更新dp[i]
为dp[j] + 1
,表示在之前的最长递增子序列基础上,加上当前位置可以构成更长的递增子序列。这个过程相当于求解以nums[i]
结尾的最长递增子序列的长度。dp[i]
时,判断当前最长递增子序列的和是否大于K,如果大于,则需要缩短当前最长递增子序列的长度。具体做法是:从i
位置倒序遍历到0,找到一个满足dp[x] == dp[i] - 1
的位置x
,然后将sum
减去nums[x]
,表示从最长递增子序列中删掉了nums[x]
这个数,然后将dp[i]
更新为dp[x]
,表示从当前位置重新开始构建一个更短的递增子序列。sum
值,表示当前最长递增子序列的和值。最终的答案为dp
数组中的最大值。
def get_longest_increasing_subsequence(nums: List[int], k: int) -> int:
n = len(nums)
dp = [1] * n
sums = [nums[i] for i in range(n)]
ans = 0
for i in range(n):
for j in range(i):
if nums[i] > nums[j] and dp[j] + 1 > dp[i]:
dp[i] = dp[j] + 1
sums[i] = sums[j] + nums[i]
ans = max(ans, dp[i])
if sums[i] > k:
for j in range(i-1, -1, -1):
if dp[j] == dp[i] - 1:
sums[i] -= nums[j]
dp[i] = dp[j]
break
return ans