方法一【提交超时】——设计起点、终点、个数【O(n^3)】
int maxSubArray(vector<int>& nums) {
int max = nums[0];
for(int i = 0; i < nums.size(); ++i)
{
for (int j = i; j < nums.size(); ++j)
{
int sum = 0;
for (int number = 0; number < j - i + 1; ++number)
{
sum += nums[i+number];
}
if(sum > max)
max = sum;
}
}
return max;
方法二【打败3%】——设计起点、遍历所有该起点子串【O(n^2)】
int max = nums[0];
for(int i = 0; i < nums.size(); ++i)
{
int sum = 0;
for (int number = 0; number < nums.size() - i; ++number)
{
sum += nums[i+number];
if(sum > max)
max = sum;
}
}
return max;
方法三:分治法【内涵迭代】
①直接分成左右子串:
int algo(vector<int> &nums, int start, int end)
{
int Maxleft, Maxright; //最大左/右子串和
if(start == end) //左右端点相同
return nums[start];
int middle = (start + end) / 2;
Maxleft = algo(nums, start, middle); //迭代左子串
Maxright = algo(nums, middle + 1 ,end); //迭代右字串
int MaxleftBorder = nums[middle], MaxrightBorder = nums[middle + 1];
int leftBordersum = 0,rightBordersum = 0;
for (int i = middle; i >=start ; i--) //左子串包含右端点的子串和
{
leftBordersum += nums[i];
if(leftBordersum > MaxleftBorder)
MaxleftBorder = leftBordersum;
}
for (int i = middle + 1; i <= end ; i++) //右子串包含左端点的子串和
{
rightBordersum += nums[i];
if(rightBordersum > MaxrightBorder)
MaxrightBorder = rightBordersum;
}
int doubleborder = MaxrightBorder + MaxleftBorder; //跨子串最大和
Maxleft = max(doubleborder, Maxleft);
Maxright = max(doubleborder, Maxright);
return max(Maxright, Maxleft);
}
int maxSubArray(vector<int>& nums) {
if(nums.size() == 0)
return 0;
else
return algo(nums, 0, nums.size()-1);
}
②分成 中点 和左右子串
int algo(vector<int> &nums, int start, int end)
{
int Maxleft, Maxright;
if(start > end)
return INT_MIN; // 此处不是返回0,比如{-2,-1},分治以后变为左中右n{},-1,{-2}三部分。左半部分{}应返回INT_MIN
if(start == end)
return nums[start];
int middle = (start + end) / 2;
Maxleft = algo(nums, start, middle - 1);
Maxright = algo(nums, middle + 1 ,end);
int MaxleftBorder = nums[middle], MaxrightBorder = nums[middle];
int leftBordersum = 0,rightBordersum = 0;
for (int i = middle; i >=start ; i--)
{
leftBordersum += nums[i];
if(leftBordersum > MaxleftBorder)
MaxleftBorder = leftBordersum;
}
for (int i = middle; i <= end ; i++)
{
rightBordersum += nums[i];
if(rightBordersum > MaxrightBorder)
MaxrightBorder = rightBordersum;
}
int doubleborder = MaxrightBorder + MaxleftBorder - nums[middle];
Maxleft = max(doubleborder, Maxleft);
Maxright = max(doubleborder, Maxright);
return max(Maxright, Maxleft);
}
int maxSubArray(vector<int>& nums) {
if(nums.size() == 0)
return 0;
else
return algo(nums, 0, nums.size()-1);
}
方法四:动态规划
图片内容转自,详见原作者:https://www.cnblogs.com/coderJiebao/p/Algorithmofnotes27.html
int maxSubArray(vector<int>& nums) {
int len=nums.size();
if(len==0) return 0;
if(len==1) return nums[0];
vector<int> dp(len,0);
dp[0] = nums[0];
int max_num = dp[0];
for (int i = 1; i< nums.size(); ++i)
{
if(dp[i-1]>0)
dp[i]=dp[i-1]+nums[i];
else
dp[i]=nums[i];
max_num = max(dp[i], max_num);
}
return max_num;
}