子数组和的最大值问题|青训营

154 阅读3分钟

问题描述

小U手上有一个整数数组,他想知道如果从数组中删除任意一个元素后,能得到的长度为 k 的子数组和的最大值。你能帮小U计算出这个结果吗?
如果数组恰好为 k 个元素,那么不进行删除操作。


测试样例

样例1:

输入:n = 5,k = 3,nums = [2, 1, 3, -1, 4]
输出:8

样例2:

输入:n = 6,k = 2,nums = [-1, -1, 5, -2, 3, 4]
输出:8

样例3:

输入:n = 4,k = 2,nums = [-5, -3, 2, 1]
输出:3

题目分析

删除数组的一个数,使其连续的长度为 k 的子数组和有最大值,如果数组恰好为 k 个元素,那么不进行删除操作。首先我能想到的就是直接删除数组中最小的数字,利用贪心算法的思想这样子数组和只可能比原来的大而不会小。同时利用前缀和,这样后面再比较长度为k的子数组和就比较简单了就是pre_nums[i] -pre_nums[i -k],然后输出最大值 于是我就写下了第一版代码:

def solution(n, k, nums):
    if n == k :
        return sum(nums)
    min_index = nums.index(min((nums)))
    nums.pop(min_index)
    pre_sum = [0]*(n - 1)
    pre_sum[0] = nums[0]
    for i in range(0,n-2):
        pre_sum[i + 1] = nums[i + 1] +pre_sum[i]
    res = []
    res.append(pre_sum[k-1])
    for i in range(k,n-1):
        res.append(pre_sum[i]-pre_sum[i-k])
    return max(res)

if __name__ == "__main__":
    # Add your test cases here
    print(solution(5, 3, [2, 1, 3, -1, 4]) == 8)

但是第四个样例报错:

输入
n= 11 
k=2 
nums=[-16,-20,-18,-4,-20,4,7,9,7,25,-10]
你的输出=32
预期输出=34

经过思考,我发现不能单纯删除整个数组的最小值,于是我尝试再将子数组长度+1,然后删除这个区间里面的最小值。于是就有了我的第二版代码,带debug版

def solution(n, k, nums):
    if n == k :
        return sum(nums)
    pre_sum = [0]*(n)
    pre_sum[0] = nums[0]
    for i in range(0,n-1):
        pre_sum[i + 1] = nums[i + 1] +pre_sum[i]
    # print(pre_sum)
    res = []
    res.append(pre_sum[k])
    for i in range(k+1,n):
        res.append(pre_sum[i]-pre_sum[i-k-1])
    # print(res)
    ans = max(res)
    # print(ans)
    max_index = res.index(max((res)))
    min_index = max_index + k + 1
    # print(max_index,min_index)
    res_range = nums[max_index:min_index]
    # print(res_range)
    max_num = min(res_range)
    # print(max_num)
    ans -=max_num
    return ans
if __name__ == "__main__":
    # Add your test cases here
    print(solution(5, 3, [2, 1, 3, -1, 4]) == 8)

但是我发现贪心的思想会陷入局部最优解的情况,因为这一步ans = max(res),所以我就上网查找了求子数组和的几种方式:连续子数组的最大和问题(五种解法)-CSDN博客受此博客启发,修改了我的代码,实现时间复杂度为Q(n)的正确思路,同时要注意边界问题。

def solution(n, k, nums):
    if n == k :
        return sum(nums)
    nums = [0]+nums
    print(nums)
    pre_sum = [0]*(n+1)
    pre_sum[0] = nums[0]
    ans = -float('inf')
    for i in range(0,n):
        pre_sum[i + 1] = nums[i + 1] +pre_sum[i]
        if i >= k:
            min_index = i - k + 1 
            max_index = i + 2
            # print(min_index,max_index,i +1,i-k)
            ans = max(ans,pre_sum[i +1]-pre_sum[i-k]- min(nums[min_index:max_index]))
    return ans
if __name__ == "__main__":
    # Add your test cases here
    print(solution(7,5,[-13,-10,9,-15,-25,17,-15]) == -12)