力扣53 最大子数和
题目描述
给你一个整数数组 nums
,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
子数组 是数组中的一个连续部分。
输入输出样例
输入:nums = [-2,1,-3,4,-1,2,1,-5,4]
输出:6
解释:连续子数组 [4,-1,2,1] 的和最大,为 6 。
输入:nums = [1]
输出:1
输入:nums = [5,4,-1,7,8]
输出:23
解法1:暴力解法
//解法1:暴力解法,超时
int maxSubArray(vector<int>&nums)
{
//定义左指针和右指针
int left,right;
vector<int>res;
if(nums.size()<=1)
{
return nums[0];
}
int length=nums.size();
for(left=0;left<length;left++)
{
int maxValue=nums[left];
int tempValue=nums[left];
for(right=left+1;right<length;right++)
{
tempValue=tempValue+nums[right];
if(tempValue>maxValue)
{
maxValue=tempValue;
}
}
res.push_back(maxValue);
}
int maxValue=res[max_element(res.begin(),res.end())-res.begin()];
return maxValue;
}
解法2:贪心算法
//解法2:使用贪心算法
int maxSubArray2(vector<int>&nums)
{
int length=nums.size();
if(length==1)
{
return nums[0];
}
//初始化最大和和当前和
int maxSum=nums[0];
int currSum=nums[0];
for(int i=1;i<length;i++)
{
//只要前面几项相加大于0那么便可以加上去
//否则则从新开始
if(nums[i]>currSum+nums[i])
{
currSum=nums[i];
}
else{
currSum=currSum+nums[i];
}
maxSum=max(currSum,maxSum);
}
return maxSum;
}
解法3,动态规划
//解法3:动态规划,若当前一个元素大于0,则将其加到当前元素上
int maxSubArray3(vector<int>&nums)
{
int length=nums.size();
//建立动态规划数组
vector<int>dp(length);
//设置初始条件
dp[0]=nums[0];
for(int i=1;i<length;i++)
{
//如果前面一个元素大于0,则将其加到当前元素上
if(dp[i-1]>0)
{
dp[i]=dp[i-1]+nums[i];
}
else{
dp[i]=nums[i];
}
}
//返回dp数组中最大的一个值
int maxValue=dp[max_element(dp.begin(),dp.end())-dp.begin()];
return maxValue;
}
解法4,分治算法实现
//解法4,使用分治法
int maxSubArray4(vector<int>&nums)
{
int length=nums.size();
if(length==1)
{
return nums[0];
}
return maxSubArraySum(nums,0,length-1);
}
int maxSubArraySum(vector<int>nums,int left,int right)
{
if(left==right)
{
return nums[left];
}
//分治法的使用
int mid=left+(right-left)/2;
int maxValue=max3(maxSubArraySum(nums,left,mid),maxSubArraySum(nums,mid+1,right),maxCrossingSum(nums,left,mid,right));
return maxValue;
}
//计算骑压在中间的值
int maxCrossingSum(vector<int>nums,int left,int mid,int right)
{
int sum=0;
int leftSum=INT_MIN;
//计算以mid结尾的最大的子数组之和
for(int i=mid;i>=left;i--)
{
sum+=nums[i];
if(sum>leftSum)
{
leftSum=sum;
}
}
sum=0;
int rightSum=INT_MIN;
//计算 以mid+1开始的 最大的子数组之和
for(int i=mid+1;i<=right;i++)
{
sum+=nums[i];
rightSum=max(sum,rightSum);
}
return leftSum+rightSum;
}
int max3(int num1,int num2,int num3)
{
return max(num1,max(num2,num3));
}