Kadane算法解决79和102 | 豆包MarsCode AI刷题

156 阅读5分钟

1. 最大子数列问题

在计算机科学中,最大子数列问题(英语:Maximum subarray Problem)的目标是在数列的一维方向找到一个连续的子数列,使该子数列的和最大。例如,对一个数列[−2, 1 , −3, 4, −1, 2, 1, −5, 4],其连续子数列中和最大[4, −1, 2, 1],其和为6。

虽然这个问题可以用几种不同的算法技术来解决,包括蛮力法、分而治之法、动态规划、简化为最短路径,但一种称为 Kadane 算法的简单单遍算法可以有效地解决这个问题。

Kadane算法的核心思想是通过局部最优解构建全局最优解。 具体来说,它通过维护两个变量来帮助计算:

①当前子数组和(current_sum):记录当前正在考察的连续子数组的和。

②最大子数组和(max_sum):记录到目前为止找到的最大子数组和。

算法的关键在于不断地更新这两个变量:

①当计算当前元素时,如果将当前元素加入当前子数组和会导致更大的结果,则继续将其加入;

②否则,从当前元素重新开始新的子数组,这意味着当前子数组和重置为当前元素的值。

2. 算法实践解题

79.翻转增益的最大了数组和

小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。

102.贪心的小包

小包非常喜欢吃甜点,他收到了一次性送来的 N 个甜点,每个甜点都有一个对应的喜爱值。

但是这还不够!小包让小哥连续送来了 M 次相同的 N 个甜点,并将这些甜点首尾相接排成一排。现在,小包面前有 (N×M) 个排成一排的甜点,小包希望从中选择一段连续的甜点,使得这段甜点的总喜爱值最大化。

这里第一题思路可以是寻找所有的翻转子串后的数组并记录每个数组的最大子数列,第二题的思路可以是先构造N * M的数组,再寻找最大子数列。两题的核心问题在于如何求解最大子数列问题。这里采用Kadane算法来解决,代码如下:

"""翻转增益的最大了数组和"""
def solution(N, data_array):
    # 第一步:使用 Kadane 算法计算最大子数组和
    def kadane(arr):
        max_end_here = max_so_far = arr[0]
        for x in arr[1:]:
            max_end_here = max(x, max_end_here + x)
            max_so_far = max(max_so_far, max_end_here)
        return max_so_far

    # 第二步:翻转所有的子数组,寻找最大子数组和
    max_sum = kadane(data_array)
    for i in range(N):
        for j in range(i, N):
            # 翻转子数组 nums[i:j+1]
            flipped = data_array[:i] + data_array[i:j+1][::-1] + data_array[j+1:]
            max_sum = max(max_sum, kadane(flipped))
    
    return max_sum

if __name__ == "__main__":
    #  You can add more test cases here
    array1 = [-85, -11, 92, 6, 49, -76, 28, -16, 3, -29, 26, 37, 86, 3, 25, -43, -36, -27, 45, 87, 91, 58, -15, 91, 5, 99, 40, 68, 54, -95, 66, 49, 74, 9, 24, -84, 12, -23, -92, -47, 5, 91, -79, 94, 61, -54, -71, -36, 31, 97, 64, -14, -16, 48, -79, -70, 54, -94, 48, 37, 47, -58, 6, 62, 19, 8, 32, 65, -81, -27, 14, -18, -34, -64, -97, -21, -76, 51, 0, -79, -22, -78, -95, -90, 4, 82, -79, -85, -64, -79, 63, 49, 21, 97, 47, 16, 61, -46, 54, 44]
    print(solution(5, [1,2,3,-1,4]) == 10 )
    print(solution(100, array1) == 1348)
"""贪心的小包"""
def solution(N, M, data):
    # 拼接字符串
    new_data = [0] * (N * M)
    
    for i in range(M):
        for j in range(N):
            new_data[i*N + j] = data[j]

    # Kadane算法
    maxSoFar = float('-inf')
    maxEndingHere = 0

    for i in range(len(new_data)):
        maxEndingHere += new_data[i]

        if maxSoFar < maxEndingHere:
            maxSoFar = maxEndingHere

        # 如果maxEndingHere小于0,重置为0
        if maxEndingHere < 0:
            maxEndingHere = 0
        

    return maxSoFar


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

3. AI刷题

在贪心小包这题中,直接问ai就可以得到相应的提示了,一步步将问题分解,得到相应的提示信息,甚至有些 题目ai都可以直接解出来,不需要debug。所以ai刷题有如下好处:

高效性

  • 快速解题:AI工具能够快速给出问题的解答或提示,帮助用户节省时间。
  • 实时反馈:AI可以即时提供对代码的反馈和建议,帮助用户快速纠正错误。

减少挫败感

  • 降低学习门槛:AI的帮助可以使难题变得更容易理解,从而减轻学习过程中遇到的挫败感。
  • 鼓励探索:AI可以鼓励用户主动尝试更多的题目,增加学习的乐趣。

错误分析与反馈

  • 代码质量优化:AI可以检测代码中的潜在问题,并提供改进建议,从而提高代码质量。
  • 总结和回顾:通过分析用户过去的错误,AI可以帮助用户识别常见的误区和改进方向,推动有效的复习。