- C++ 实现
// -*- coding: utf-8 -*-
// @ Date : 2020/5/20 13:14
// @ Author : RichardLau_Cx
// @ file : Richard.cpp
// @ IDE : Dex-C++
// @ Source : luogu
// 算法思想:分治法
#include <iostream>
using namespace std;
int maxSum(int *sequence, int x, int y)
{
int L, R, v, m;
// 第一步:划分问题
m = (x + y) / 2; // 单纯的"/"号是朝零方向的取整,而不是向下取整,如:5/2=2, -5/2=-2
// m = x + (y - x) / 2;
// 第二步:递归求解
if (y - x == 1)
{ // 递归出口
return sequence[x];
}
int maxs = max(maxSum(sequence, x, m), maxSum(sequence, m, y));
// 当前左子序列总和
v=0;
L = sequence[m-1];
for (int i=m-1; i >= x; i--)
{
L = max(L, v += sequence[i]); // 相当于每加一次,就进行一次比较
}
// 当前右子序列总和
v=0;
R = sequence[m];
for (int i=m; i < y; i++)
{
R = max(R, v += sequence[i]);
}
// 第三步,合并问题
return max(maxs, R+L);
}
int main()
{
// 对于100%的数据,保证:1 <= n <= 2 * 10^5,-10^4 <= ai <= 10^4;
int n; // 序列长度
cin >> n;
int sequence[n];
for (int i=0; i < n; i++)
{
// scanf("%d", &sequence[i]);
cin >> sequence[i];
}
// cout << "maxSum(sequence, 0, n): " << maxSum(sequence, 0, n);
cout << maxSum(sequence, 0, n) << endl;
/*
for (int i=0; i < n; i++)
{
// printf("%d ", sequence[i]);
cout << sequence[i] << ' ';
}
*/
return 0;
}
- 测试代码
// -*- coding: utf-8 -*-
// @ Date : 2020/5/20 13:14
// @ Author : RichardLau_Cx
// @ file : Richard.cpp
// @ IDE : Dex-C++
// @ Source : 紫书-P223
#include <iostream>
using namespace std;
int maxSum(int *A, int x, int y);
int main()
{
int array[] = {2, -4, 3, -1, 2, -4, 3}; // 传入数列,数组的索引是从零开始的
int x = 0; // 子段左边界
int y = 6; // 子段右边界
cout << "maxSum(array, x, y): " << maxSum(array, x, y) << endl;
return 0;
}
int maxSum(int *A, int x, int y)
{ // 返回数组在左闭右开区间 [x, y) 中的最大连续和
int v; // 当前值之和
int L; // 左边的最大连续和
int R; // 右边的最大连续和
int maxs; // 左右边合并起来的最大值
if (y - x == 1) // 递归出口
{ // 因为区间右开,所以只剩下了x(左边),直接返回值
return A[x];
}
int m = x + (y - x) / 2; // 分治第一步:划分成 [x, m) 和 [m, y),m刚好为x和y的中间点
maxs = max(maxSum(A, x, m), maxSum(A, m, y)); // 分治第二步:递归求解
// int v, L, R;
v = 0;
L = A[m-1]; // 分治第三步:合并(1) --- 从分界点开始,往左的最大连续和-L
for (int i = m-1; i >= x; i--)
{
L = max(L, v += A[i]); // 从当前中点,向左延伸找左边的最大连续和
}
v = 0;
R = A[m]; // 分治第三步:合并(2) --- 从分界点开始,往右的最大连续和-R
for (int i = m; i < y; i++)
{
R = max(R, v += A[i]); // 从当前中点,向右延伸找右边的最大连续和
}
return max(maxs, L+R); // 把子问题的解,与当前L与R的和做比较
}