题目:
给定一个整数序列(数组)nums ,找到一个具有最大和的连续子序列(子序列最少包含一个元素),返回其最大和
示例:
输入: [-2,1,-3,4,-1,2,1,-5,4]
输出: 6
原因: 连续子数组 [4,-1,2,1] 的和最大,为 6
代码:
方法一:暴力循环
#include <iostream>
#define _for(a,b,c) for(int a=b;a<c;a++)
using namespace std;
int main()
{
int nums[9] = {-2,1,-3,4,-1,2,1,-5,4};
int k = sizeof(nums)/sizeof(nums[0]);//nums是数组
int max_sum = nums[0];
_for(i,0,k)
{
int sum = 0;
_for(j,i,k)
{
sum+=nums[j];
if(sum>max_sum) max_sum = sum;
}
}
cout<<max_sum;
return 0;
}
复杂度为 O(n2)
此为 leecode 上通过编译显示的数据
顺便说一下,在 leecode 上不能用 sizeof(nums)/sizeof(nums[0]) ,会报错,应用 nums.size() ,因为 leecode 输入的是 vector容器,而 vector容器 是存在 nums.size() 方法的
方法二:分治法
#include <iostream>
#define _for(a,b,c) for(int a=b;a<c;a++)
using namespace std;
int fenzhi(int nums[],int left,int right);
int mid2(int nums[],int mid,int left,int right);
int main()
{
int nums[9] = {-2,1,-3,4,-1,2,1,-5,4};
int result = INT_MIN;
int k = sizeof(nums)/sizeof(nums[0]);
result = fenzhi(nums,0,k-1);
cout<<result;
return 0;
}
int fenzhi(int nums[],int left,int right)
{
if(left==right) return nums[left];
int mid = (left+right)/2;
int leftmax = fenzhi(nums,left,mid); //从 left 开始,而不是 0
int rightmax = fenzhi(nums,mid+1,right);
int result = max(leftmax,rightmax);
int midmax = mid2(nums,mid,left,right);
result = max(result,midmax);
return result;
}
int mid2(int nums[],int mid,int left,int right)
{
int leftsum = nums[mid],rightsum = nums[mid+1],sum = 0;
for(int i = mid;i>=left;i--) leftsum = max(leftsum,(sum+=nums[i]));
sum = 0;
for(int i = mid+1;i<=right;i++) rightsum = max(rightsum,(sum+=nums[i]));
return (leftsum+rightsum); //注意返回值是二者相加,而不是取最大值
}
复杂度为 O(nlogn),虽然 分治法 复杂度比 暴力法 低,但是对于此题,数据越小, 结果越不明显
再说一些关于 leecode 的事项
leecode 不用考虑定义顺序(即不用写声明直接定义 )
lecode不用写头文件,或相当于自带<bits/stdc++.h> (暂时如此认为)
方法三:贪心
#include <iostream>
#define _for(a,b,c) for(int a=b;a<c;a++)
using namespace std;
int main()
{
int nums[9] = {-2,1,-3,4,-1,2,1,-5,4};
int maxSum=nums[0],sum=0;
int k = sizeof(nums)/sizeof(nums[0]);
_for(i,0,k)
{
sum+=nums[i];
if(sum>maxSum) maxSum=sum;
if(sum<0) sum=0;
}
cout<<maxSum;
return 0;
}
复杂度为 O(n),同理,数据越小, 结果越不明显
此题中,此方法别名:及时处理
因为全程只遍历一遍,故遍历到哪儿,哪儿就是最优解
解析本题贪心
若不理解什么是贪心,建议参考此篇博客:贪心—基本概念,本题的方法主要运用了的思想:先将 sum 和 maxsum 赋值为第一个元素的值,若 sum 小于 0,则重新为 sum 赋值为 0,并加上下一个元素的值,继续累加,若 sum 大于 0,接下来也继续累加,但要在 sum 小于 0 时重新为其赋值为 0,并加上下一个元素的值,继续累加,并每加一次与 maxsum 进行比较、替换
若还是不能理解,不妨看看这句话