📅  最后修改于: 2023-12-03 14:56:45.436000             🧑  作者: Mango
给定一个长度为n的整数数组nums和一个整数k,你需要将nums中最多k个元素修改为任意值,使得修改后的数组的和最大。返回最大和。
对于没有k的限制,是一个很简单的问题,可以用贪心算法求解。遍历整个数组,如果一个数比前一个数大就将其加入总和,否则忽略。这也就意味着我们可以使用贪心的思路进行解题。
然而加入了k的限制后,算法需要有所改进。考虑对nums进行处理,记录前i个数中的最大连续子序列和left[i],以及后i个数中的最大连续子序列和right[i]。可以得到left和right的转移方程:
left[i] = max(left[i-1]+nums[i], nums[i])
right[i] = max(right[i+1]+nums[i], nums[i])
由此可得到一个长度为n-k+1的数组,每个元素代表该下标对应的k个数可以替换的最大和。此时我们将这个数组中的最大值与原数组求和,即为所求。
这个转移方程的时间复杂度为O(n),而计算左右两侧的最大连续子序列和只需要一次遍历,因此总时间复杂度为O(n)。
def maxSum(nums, k):
n = len(nums)
left = [0] * n
right = [0] * n
left[0], right[n-1] = nums[0], nums[n-1]
for i in range(1, n):
j = n - i - 1
left[i] = max(left[i-1] + nums[i], nums[i])
right[j] = max(right[j+1] + nums[j], nums[j])
res = max(nums)
for i in range(k+1):
for j in range(n-k-1, n):
if i+j-k >= 0 and i+j-k < n:
temp = sum(nums[i:i+j-k+1])
if i > 0:
temp += left[i-1]
if j < n-1:
temp += right[j+1]
res = max(res, temp)
return res
精确地k更改后可获得的最大数组和问题可以用贪心的思路进行解题,但加入k的限制后需要有所改进。处理出每个下标对应的k个数可以替换的最大和,再取其中的最大值与原数组求和,即为所求,总时间复杂度为O(n)。