算法1
- 算法思想
基本思想:穷举式的尝试所有可能,通过三层循环计算所有子序列的和。
算法步骤:
1.第一层循环从0到N-1,确定子序列的开始位置;
2.第二层循环从第一层循环变量开始到N-1,确定子序列的结束位置;
3.第三层循环从第一层循环变量开始到第二层循环变量结束,计算这个子序列的和,并与最大子序列和比较,如果大于最大子序列和就赋值给最大子序列和。
- 运行时间
O(N³)
- 算法实现
int MaxSubSequenceSum_1(int A[], int N)
{
int ThisSum, MaxSum,i, j, k;
MaxSum = 0;
for(i=0;i<N;i++)
for (j = i; j < N; j++)
{
ThisSum = 0;
for (k = i; k <= j; k++)
ThisSum += A[k];
if (ThisSum > MaxSum)
{
MaxSum = ThisSum;
}
}
return MaxSum;
}
算法2
- 算法思想
基本思想:穷举所有可能,通过两层循环实现,与第一个算法相比较,减小了第三层循环,不需要每次都从第一层循环变量的位置开始累加子序列。
算法步骤:
1.第一层循环从0到N-1,确定子序列的初始位置;
2.第二层循环从第一层的循环变量开始到N-1,对当前序列和进行累加数组中的元素,并与最大子序列和比较,如果大于最大子序列和,则赋值给最大子序列和。
- 运行时间
O(N²)
- 算法实现
int MaxSubSequenceSum_2(int A[],int N) { int ThisSum, MaxSum, i, j; MaxSum = 0; for (i = 0; i < N; i++) { ThisSum = 0; for (j = i; j < N; j++) { ThisSum += A[j]; if (ThisSum > MaxSum) MaxSum = ThisSum; } } return MaxSum; }
算法3
- 算法思想
基本思想:通过分治思想,最大子序列和可能在三处出现,或者整个出现在输数据的左半部,或者整个出现在右半部,或者跨越输入数据的中部从而占据左右两部分。前两种情况递归求解,第三种情况的最大和通过求出前半部分的最大和(包含前半部分的最后一个元素)以及后半部分的最大和(包含后半部分的第一个元素)而得到。
算法步骤:
1.递归的基准情况处理,及如果Left==Right,并且当该元素最大时,它就是最大子序列;
2.计算序列的中间值并,递归求解最大子序列在全部在左半部分出现,或者全部在右半部份出现的情况;
3.使用两个循环分别计算前半部分的最大和(包含前半部分的最后一个元素)以及后半部分的最大和(包含后半部分的第一个元素);
4.返回三种情况计算出最大和的最大一种情况并返回。
- 运行时间
O(N log N)
- 算法实现
int Max3(int i, int j, int k)
{
return k > (i > j ? i : j) ? k : (i > j ? i : j);
}
int MaxSum(int A[],int Left,int Right)
{
int MaxLeftSum, MaxRightSum;
int MaxLeftBoderSum, MaxRightBoderSum;
int LeftBoderSum, RightBoderSum;
int center, i;
if (Left == Right)
if (A[Left] > 0)
return A[Left];
else
return 0;
center = (Left + Right) / 2;
MaxLeftSum = MaxSum(A, Left, center);
MaxRightSum = MaxSum(A, center + 1, Right);
LeftBoderSum = MaxLeftBoderSum = 0;
for (i = center; i >= Left; i--)
{
LeftBoderSum += A[i];
if (LeftBoderSum > MaxLeftBoderSum)
MaxLeftBoderSum = LeftBoderSum;
}
RightBoderSum = MaxRightBoderSum = 0;
for (i=center+1;i<=Right;i++)
{
RightBoderSum += A[i];
if (RightBoderSum > MaxRightBoderSum)
MaxRightBoderSum = RightBoderSum;
}
return Max3(MaxLeftSum, MaxRightSum, MaxLeftBoderSum+ MaxRightBoderSum);
}
int MaxSubSequenceSum_3(int A[], int N)
{
return MaxSum(A, 0, N - 1);
}算法4
递归实现:
int mymaxSubArray(vector<int>& nums ,int i,int* pointTomaxSum)
{
int thisSum;
int temp;
if (i == 0)
return nums[i];
else
temp = mymaxSubArray(nums, i - 1,pointTomaxSum);
thisSum =(temp>0 ? temp : 0) + nums[i];
*pointTomaxSum = max(thisSum, *pointTomaxSum);
return thisSum;
}
class Solution {
public:
int maxSubArray(vector<int>& nums) {
int *pointTomaxSum;
int maxSum=nums[0];
pointTomaxSum=&maxSum;
mymaxSubArray(nums,nums.size()-1,pointTomaxSum);
return maxSum;
}
};算法5
动态规划实现:
class Solution {
public:
int maxSubArray(vector<int>& nums) {
int len=nums.size();
vector<int> thisSum(len);
thisSum[0]=nums[0];
int maxSum=nums[0];
for(int i=1;i<len;i++){
thisSum[i]=nums[i]+(thisSum[i-1] >0 ? thisSum[i-1] :0);
maxSum=max(thisSum[i],maxSum);
}
return maxSum;
}
};时间:O(N)
空间:O(N)
动态规划改进:
因为只需要保存上次计算的总和就可以了,不需要用数组维持每次计算后的总和。
修改后的代码:
class Solution {
public:
int maxSubArray(vector<int>& nums) {
int len=nums.size();
//vector<int> thisSum(len);
int thisSum=nums[0];
//thisSum[0]=nums[0];
int maxSum=nums[0];
for(int i=1;i<len;i++){
thisSum=nums[i]+(thisSum >0 ? thisSum :0);
maxSum=max(thisSum,maxSum);
}
return maxSum;
}
};或者从0开始,这样修改;
class Solution {
public:
int maxSubArray(vector<int>& nums) {
int len=nums.size();
//vector<int> thisSum(len);
int thisSum=0;
//thisSum[0]=nums[0];
int maxSum=nums[0];
for(int i=0;i<len;i++){
thisSum=nums[i]+(thisSum >0 ? thisSum :0);
maxSum=max(thisSum,maxSum);
}
return maxSum;
}
};
时间:O(N)
空间:O(1)
算法6
- 算法思想
基本思想:从数组的第一个元素开始累加到子序列和,当子序列和大于最大子序列和,则将子序列和赋值给最大子序列和,否则判断子序列和是否小于0,小于0就将子序列和赋值0。这句话的意思是前面所有序列和为负数的话,就抛弃前面的所有序列,从当前序列重新累加,因为将前面的序列加入会使得和变小。</div><div>说明:该算法一个附带的优点是,它只对数据进行一次扫描,一旦A[i]被读入并被处理,它就不再需要被记忆。不仅如此,在任意时刻,算法都呢个对它已经读入的书给出子序列问题的正确答案。具有这种性质的算法叫做联机算法(on-line
algorithm)。
算法步骤:
1.一个循环从0到N-1,实现对所有元素的遍历;
2.将每个元素累加到子序列和,如果子序列和大于最大子序列和,就赋值给最大子序列和,否则判断子序列和是否小于0,小于0就将子序列和赋值0。
- 运行时间
O(N)
- 算法实现
long long MaxSubSequenceSum_4(long long A[], long long N)
{
long long ThisSum,MaxSum,i;
ThisSum=0;
MaxSum=A[0]; //注意,最大值可能是第一个元素
for(i=0;i<N;i++)
{
ThisSum+=A[i];
if(ThisSum>MaxSum)
MaxSum=ThisSum;
if(ThisSum<0) //不能添加else
ThisSum=0;
}
return MaxSum;
}
4603

被折叠的 条评论
为什么被折叠?



