最大连续子数组和问题 | 豆包MarsCode AI刷题

62 阅读4分钟

写在前面

青训营接近尾声,蒜法蒻媾下个月打算法氵赛,每天一道难题冲冲冲!今天准备复习的是最大连续子数组和问题,众所周知最大连续子数组和的经典解法是Kadane算法,下面来看看题目

问题描述

小C拿到了一个数组,他可以进行最多一次操作:将一个元素修改为任意给定的x。小C想知道,经过这次修改后,能够得到的连续子数组的最大和是多少。


测试样例

样例1:

输入:n = 5 ,x = 10 ,a = [5, -1, -5, -3, 2]
输出:15

样例2:

输入:n = 2 ,x = -3 ,a = [-5, -2]
输出:-2

样例3:

输入:n = 6 ,x = 10 ,a = [4, -2, -11, -1, 4, -1]
输出:15

解题思路

首先了解一下Kadane算法的基本思路,Kadane算法是一个经典的用于解决最大连续子数组和的动态规划算法,通过维护更新一个局部最大值和一个全局最大值来得到最优解。这个算法实现也很好理解,一般分为以下两步:

1. 初始化: 初始化局部最大变量max_ending_here和全局最大变量max_so_far为数组第一个元素.

2. 遍历数组: 遍历数组,若局部最大值加上当前值比局部最大值还要大,则扩展子数组更新最大值,反之从当前元素开始一个新的子数组求和,更新完局部最大值后再把局部最大值和全局最大值比较,更新全局最大值.

实现完Kadane算法后,这题剩下的步骤就很简单了,再遍历数组一次,依次修改每个元素,计算每次修改后的最大连续子数组和,再恢复修改的元素遍历下一个,直到遍历完成返回最大值。

题解

#include <iostream>
#include <vector>
#include <algorithm>

int kadane(const std::vector<int>& a) {
    // Kadane算法实现
    int max_ending_here = a[0];
    int max_so_far = a[0];
    for (int i = 1; i < a.size(); ++i) {
        max_ending_here = std::max(a[i], max_ending_here + a[i]);
        max_so_far = std::max(max_so_far, max_ending_here);
    }
    return max_so_far;
}

int solution(int n, int x, std::vector<int> a) {
    // 尝试修改每个元素为x,计算修改后的最大子数组和
    int max_sum_with_change = -999999999; //给个很小的数
    for (int i = 0; i < n; ++i) {
        int original_value = a[i];
        a[i] = x;  // 修改当前元素为x
        int current_max_sum = kadane(a);
        max_sum_with_change = std::max(max_sum_with_change, current_max_sum);
        a[i] = original_value;  // 恢复原值
    }
    
    // 返回不修改和修改后的最大子数组和中的最大值
    return max_sum_with_change;
}

int main() {
    std::cout << (solution(5, 10, {5, -1, -5, -3, 2}) == 15) << std::endl;
    std::cout << (solution(2, -3, {-5, -2}) == -2) << std::endl;
    std::cout << (solution(6, 10, {4, -2, -11, -1, 4, -1}) == 15) << std::endl;
    std::cout << (solution(16, 1, {17,17,4,13,11,3,6,13,7,13,13,13,6,16,6,11}) == 167) << std::endl;
}

看看AI的修改建议

你的代码整体思路是正确的,但在实现细节上可能存在一些问题。以下是一些可能的改进建议:

  1. 初始值问题:在 solution 函数中,max_sum_with_change 的初始值设置为 -999999999,这可能会导致在一些特殊情况下出现问题。建议使用 std::numeric_limits<int>::min() 来初始化,以确保初始值是最小的整数。
  2. Kadane算法的使用:你在 solution 函数中对每个元素进行修改并调用 kadane 函数来计算最大子数组和。这种方法的时间复杂度是 O(n^2),因为每次修改一个元素后都需要重新计算整个数组的最大子数组和。可以考虑优化这个过程,避免重复计算。
  3. 测试用例:你在 main 函数中添加了一些测试用例,但这些测试用例可能不足以覆盖所有边界情况。建议添加更多边界测试用例,例如全负数数组、全正数数组、只有一个元素的数组等。

关键改进点:

  1. 初始值:使用 std::numeric_limits<int>::min() 来初始化 max_sum_with_change
  2. Kadane算法:保持不变,但确保在 solution 函数中正确使用。
  3. 测试用例:保持不变,但建议添加更多边界测试用例。

希望这些建议对你有帮助!如果你有更多问题,欢迎继续提问。