前言
这道题目有三种解法:
题目描述
给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
示例:
输入: [-2,1,-3,4,-1,2,1,-5,4],
输出: 6
解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。
实现方法
一、暴力求解
int MaxSubseqSum1(int a[], int n) {
int CurrentSum, MaxSum = 0;
for (int i = 0; i < n; i++) {
CurrentSum = 0;
for (int j = i; j < n; j++) {
CurrentSum += a[j];
if (CurrentSum > MaxSum)
MaxSum = CurrentSum;
}
}
return MaxSum;
}
二、分治法
//3个数比大小,返回最大值
int MaxNum3(int a, int b, int c) {
return a > b ? a > c ? a : c : b > c ? b : c;
}
//二分法:递归。 O(nlog(n))
int BinaryMaxSubSum(int list[], int left, int right) {
int MaxLeftSum, MaxRightSum;
int MaxBoardSum, MaxLeftBoardSum = 0, MaxRightBoardSum = 0;
int i, center;
//判断递归终止条件
if (left == right) {
if (list[left] > 0)
return list[left];
return 0;
}
//进行分治,求得左序列和最大值、右序列和最大值
center = (left + right) / 2;
MaxLeftSum = BinaryMaxSubSum(list, left, center);
MaxRightSum = BinaryMaxSubSum(list, center + 1, right);
//求中间跨界的和最大值
int LeftBoardSum = 0, RightBoardSum = 0;
for (i = center; i >= left; i--) {
LeftBoardSum += list[i];
if (LeftBoardSum > MaxLeftBoardSum) {
MaxLeftBoardSum = LeftBoardSum;
}
}
for (i = center + 1; i <= right; i++) {
RightBoardSum += list[i];
if (RightBoardSum > MaxRightBoardSum) {
MaxRightBoardSum = RightBoardSum;
}
}
MaxBoardSum = MaxLeftBoardSum + MaxRightBoardSum;
//比较三者的大小,返回最大值
return MaxNum3(MaxBoardSum, MaxLeftSum, MaxRightSum);
}
int MaxSubseqSum2(int a[], int n) {
return BinaryMaxSubSum(list, 0, n - 1);
}
三、在线处理
int MaxSubseqSum3(int a[], int n) {
int CurrentSum = 0, MaxSum = a[0];
for (int i = 0; i < n; i++) {
CurrentSum += a[i];
if (CurrentSum > MaxSum) {
MaxSum = CurrentSum;
}
if (CurrentSum < 0) {
CurrentSum = 0; //如果子序列和为负,则置零
}
}
return MaxSum;
}
总结
比较上面的三种方法,第三种方法最好。但是分治法的思想也很精妙,需要掌握。