写在前面
青训营接近尾声,蒜法蒻媾下个月打算法氵赛,每天一道难题冲冲冲!今天准备复习的是最大连续子数组和问题,众所周知最大连续子数组和的经典解法是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的修改建议
你的代码整体思路是正确的,但在实现细节上可能存在一些问题。以下是一些可能的改进建议:
- 初始值问题:在
solution函数中,max_sum_with_change的初始值设置为-999999999,这可能会导致在一些特殊情况下出现问题。建议使用std::numeric_limits<int>::min()来初始化,以确保初始值是最小的整数。- Kadane算法的使用:你在
solution函数中对每个元素进行修改并调用kadane函数来计算最大子数组和。这种方法的时间复杂度是O(n^2),因为每次修改一个元素后都需要重新计算整个数组的最大子数组和。可以考虑优化这个过程,避免重复计算。- 测试用例:你在
main函数中添加了一些测试用例,但这些测试用例可能不足以覆盖所有边界情况。建议添加更多边界测试用例,例如全负数数组、全正数数组、只有一个元素的数组等。关键改进点:
- 初始值:使用
std::numeric_limits<int>::min()来初始化max_sum_with_change。- Kadane算法:保持不变,但确保在
solution函数中正确使用。- 测试用例:保持不变,但建议添加更多边界测试用例。
希望这些建议对你有帮助!如果你有更多问题,欢迎继续提问。