目录
问题描述:
给你一个整数数组 nums
,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
子数组 是数组中的一个连续部分。
示例 1:
输入:nums = [-2,1,-3,4,-1,2,1,-5,4] 输出:6 解释:连续子数组 [4,-1,2,1] 的和最大,为 6 。
示例 2:
输入:nums = [1] 输出:1
示例 3:
输入:nums = [5,4,-1,7,8] 输出:23
实现代码与解析:
暴力法(会超时):
class Solution {
public:
int maxSubArray(vector<int>& nums)
{
int result=INT32_MIN;
//找起始位置
for(int i=0;i<nums.size();i++)
{
int sum=0;//和
//找最大和
for(int j=i;j<nums.size();j++)
{
sum+=nums[j];
if(sum>result) result=sum;
}
}
return result;
}
};
原理思路:
就是直接暴力循环,第一层循环找起始位置,第二层循环找最大值替换,不过会超时,只要数过多,计算时间想想就要很长时间,这里就是记录一下不同的解题方法而已。
贪心算法:
class Solution {
public:
//贪心算法
int maxSubArray(vector<int>& nums)
{
int result=INT_MIN;
int sum=0;
for(int i=0;i<nums.size();i++)
{
sum+=nums[i];
if(sum>result) result=sum;//更新sum
//小于零的话,直接重新开始记录
if(sum<0) sum=0;
}
return result;
}
};
原理思路:
当sum累加到负值时,我们就舍弃前面累加的值,重新开始累加,其实就相当于前面一个负数,后面一个是正数,我们肯定是要舍弃前面的负数的,相当于暴力法里重新找位置的第一层循环的操作了,不过还是要result来更新结果的,因为会出现sum依然是正值,但是变小的情况,用result记录下来最大值就不会丢失。下面是模拟的流程图:
动态规划:
class Solution {
public:
//动态规划
int maxSubArray(vector<int>& nums)
{
vector<int> dp(nums.size(),0);
dp[0]=nums[0];
int result=dp[0];
for(int i=1;i<nums.size();i++)
{
dp[i]=max(dp[i-1]+nums[i],nums[i]);
if(dp[i]>result) result=dp[i];//记录最大值
}
return result;
}
};
原理思路:
dp[ i ]数组的含义显然是以nums[ i ]为结尾的最大子数组和,递推公式就是取nums[ i-1 ] 为结尾的最大数组和加上nums[ i ]和nums[ i ]之间的最大值,result来记录最终结果,下面图给出dp数组的对应值。