Every day a leetcode
题目来源:53. 最大子数组和
解法1:暴力
两层for循环,更新最大子数组和的最大值ans。
代码:
#define INT_MIN 0x80000000
int max(int a,int b)
{
return a>b?a:b;
}
int maxSubArray(int* nums, int numsSize){
int ans=INT_MIN;
for(int i=0;i<numsSize;i++)
{
int sum=0;
for(int j=i;j<numsSize;j++)
{
sum+=nums[j];
ans=max(ans,sum);
}
}
return ans;
}
结果:
解法2:动态规划
dp[i]:表示以 nums[i] 结尾 的 连续 子数组的最大和。
状态转移方程:
归纳为:dp[i]=max{nums[i], dp[i−1]+nums[i]}
初始化dp[0]=nums[0]。
得到dp数组后,遍历一次,其中的最大值即为答案。
代码:
int max(int a,int b)
{
return a>b?a:b;
}
int maxSubArray(int* nums, int numsSize){
int *dp;
dp=(int*)malloc((numsSize+6)*sizeof(int));
dp[0]=nums[0];
for(int i=1;i<numsSize;i++)
{
dp[i]=max(dp[i-1]+nums[i],nums[i]);
}
int ans=dp[0];
for(int i=1;i<numsSize;i++)
{
ans=max(ans,dp[i]);
}
return ans;
}
结果:
解法3:贪心
基于贪心的思想:
如果 -2,1 在一起,计算起点的时候,一定是从1开始计算,因为负数只会拉低总和,这就是贪心的用处。
局部最优:当前“连续和”为负数的时候立刻放弃,从下一个元素重新计算“连续和”,因为负数加上下一个元素 “连续和”只会越来越小。
全局最优:选取最大的连续的和。
局部最优的情况下,并记录最大的“连续和”,可以推出全局最优。
做法:
- 遍历整个数组;
- 将数组的值连续相加,如果和sum大于0则一直加;
- 如果和sum小于零,则丢弃sum(sum置0);
- 遍历过程中保存最大值max。
代码:
#define INT_MIN 0x80000000
int maxSubArray(int* nums, int numsSize){
int max=INT_MIN;
int sum=0;
for(int i=0;i<numsSize;i++)
{
sum+=nums[i];
if(sum>max) max=sum;
if(sum<0) sum=0;
}
return max;
}
结果:
方法4:分治
详情见于官方题解:最大子数组和:方法二:分治