📌  相关文章
📜  精确地k更改后可获得的最大数组和(1)

📅  最后修改于: 2023-12-03 14:56:45.436000             🧑  作者: Mango

精确地k更改后可获得的最大数组和

简介

给定一个长度为n的整数数组nums和一个整数k,你需要将nums中最多k个元素修改为任意值,使得修改后的数组的和最大。返回最大和。

思路
  1. 对于没有k的限制,是一个很简单的问题,可以用贪心算法求解。遍历整个数组,如果一个数比前一个数大就将其加入总和,否则忽略。这也就意味着我们可以使用贪心的思路进行解题。

  2. 然而加入了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)。