AI 刷题 79. 翻转增益的最大子数组和 题解 | 豆包MarsCode AI刷题

85 阅读4分钟

翻转增益的最大子数组和

问题描述

小C面对一个由整数构成的数组,他考虑通过一次操作提升数组的潜力。这个操作允许他选择数组中的任一子数组并将其翻转,目的是在翻转后的数组中找到具有最大和的子数组。小C对这个可能性很感兴趣,并希望知道翻转后的数组中可能得到的最大子数组和是多少。例如,数组是 1, 2, 3, -1, 4。小C可以选择翻转子数组 -1, 4 得到 1, 2, 3, 4, -1 或者翻转 1, 2, 3, -1 得到 -1, 3, 2, 1, 4,在这两种情况下,最大的子数组和都是 10。

备注:子数组 是数组中的一个连续部分。

思路解析

暴力枚举:

  1. 计算不进行翻转时的最大子数组和

    • 使用Kadane算法来计算数组的最大子数组和。这个算法的时间复杂度是O(N),非常高效。
  2. 枚举所有可能的子数组翻转情况

    • 使用两层循环来枚举所有可能的子数组翻转情况。外层循环遍历子数组的起始位置,内层循环遍历子数组的结束位置。
    • 对于每一个子数组,将其翻转,并生成一个新的数组。
  3. 计算翻转后的数组的最大子数组和

    • 对于每一个新生成的数组,再次使用Kadane算法来计算其最大子数组和。
  4. 返回最大值

    • 比较所有情况下的最大子数组和,并返回其中的最大值。

解题步骤

. 计算原数组最大子数组和
  • 在 solution 函数内部定义了一个嵌套函数 max_subarray_sum,用于计算给定数组的最大子数组和。该函数使用了经典的动态规划思想,类似于 Kadane 算法。

  • 初始化 cur_sum(当前子数组和)和 max_sum(最大子数组和)为数组的第一个元素 arr[0]

  • 然后遍历数组 arr 中除第一个元素之外的其他元素,对于每个元素 num

    • 通过 cur_sum = max(num, cur_sum + num) 更新当前子数组和,即要么选择当前元素作为新的子数组起点(num),要么将当前元素加入到之前的子数组中(cur_sum + num),取两者中的较大值。
    • 通过 max_sum = max(max_sum, cur_sum) 更新最大子数组和,比较当前的 cur_sum 和已记录的 max_sum,取较大值作为新的 max_sum
  • 最后返回 max_sum,即原数组的最大子数组和。

2. 枚举子数组翻转情况
  • 外层循环 for left in range(N) 遍历子数组的左边界,从 0 到 N - 1
  • 内层循环 for right in range(left, N) 遍历子数组的右边界,从当前左边界 left 到 N - 1,这样可以枚举出所有可能的子数组。
  • 对于每一个确定的子数组范围(由 left 和 right 确定),通过切片操作 data_array[:left] 获取子数组左边部分,data_array[right + 1:] 获取子数组右边部分,然后使用 list(reversed(data_array[left:right + 1])) 翻转中间的子数组,将这三部分组合成一个新的数组 new_array
3. 计算翻转后数组的最大子数组和并更新结果
  • 对于每一个生成的新数组 new_array,调用 max_subarray_sum 函数计算其最大子数组和,并通过 max_sum = max(max_sum, max_subarray_sum(new_array)) 将其与之前记录的最大子数组和 max_sum 进行比较,取较大值更新 max_sum
4. 返回最终结果
  • 最后,函数返回 max_sum,即经过所有可能的子数组翻转后,能得到的最大子数组和。

时间复杂度分析

  • 计算不进行翻转时的最大子数组和的时间复杂度是O(N)。
  • 枚举所有可能的子数组翻转情况的时间复杂度是O(N^2)。
  • 对于每一个翻转后的数组,计算其最大子数组和的时间复杂度是O(N)。

因此,总的时间复杂度是O(N^3),这在N较大时可能会导致性能问题,但是这题能过。

def solution(N, data_array):
    # 计算不进行翻转时的最大子数组和(常规的最大子数组和算法)
    def max_subarray_sum(arr):
        cur_sum = max_sum = arr[0]
        for num in arr[1:]:
            cur_sum = max(num, cur_sum + num)
            max_sum = max(max_sum, cur_sum)
        return max_sum

    max_sum = max_subarray_sum(data_array)
    for left in range(N):
        for right in range(left, N):
            new_array = data_array[:left] + list(reversed(data_array[left:right + 1])) + data_array[right + 1:]
            max_sum = max(max_sum, max_subarray_sum(new_array))
    return max_sum