彦祖天天见
题目:53.最大子数组和
题目要求:
给你一个整数数组 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
第一种解法:动态规划
由题可知,到第i个位置的最大数组和的选择是继续保持i个位置的最大数组和,或者由i-1个位置的最大数组和加上第i个位置,其代码如下:
class Solution {
public:
int maxSubArray(vector<int>& nums) {
if(nums.size() == 0) return 0;
vector<int> dp(nums.size(),0);
dp[0] = nums[0];
int res=dp[0];
for(int i=1;i<nums.size();i++){
dp[i]=max(dp[i-1]+nums[i],nums[i]);
if(dp[i] > res) res = dp[i];
}
return res;
}
};
第二种解法:贪心
贪心采用累加的方式计算最大数组和,如果和为负数则马上丢弃当前位置,从下一位置重新计算;
每次循环将计算得到的最大值存入结果。
class Solution {
public:
int maxSubArray(vector<int>& nums) {
int count=0;
int res=nums[0];
for(int i=0;i<nums.size();i++){
count +=nums[i];
res = res>count?res:count;
if(count<0) count=0;
}
return res;
}
};
这一题是由上面题目演变而来
题目要求:
一个下标从 0 开始的数组的 交替和 定义为 偶数 下标处元素之 和 减去 奇数 下标处元素之 和 。
比方说,数组 [4,2,5,3] 的交替和为 (4 + 5) - (2 + 3) = 4 。
给你一个数组 nums ,请你返回 nums 中任意子序列的 最大交替和 (子序列的下标 重新 从 0 开始编号)。
一个数组的 子序列 是从原数组中删除一些元素后(也可能一个也不删除)剩余元素不改变顺序组成的数组。比方说,[2,7,4] 是 [4,2,3,7,2,1,4] 的一个子序列(加粗元素),但是 [2,4,2] 不是。
示例 1:
输入:nums = [4,2,5,3]
输出:7
解释:最优子序列为 [4,2,5] ,交替和为 (4 + 5) - 2 = 7 。示例 2:
输入:nums = [5,6,7,8]
输出:8
解释:最优子序列为 [8] ,交替和为 8 。示例 3:
输入:nums = [6,2,1,2,4,5]
输出:10
解释:最优子序列为 [6,1,5] ,交替和为 (6 + 5) - 1 = 10 。
由题目可知结果由偶数下标和减去奇数下标和,所以奇数下标的元素符号为-i,偶数下标的元素符号为i 使用两个vector容器来存储奇数和偶数的最大和,然后从中比较最大者。
偶数方程表示,以nums[i-1]
结尾的最大交替和的偶数项ou[i]
,可以选择不包含nums[i-1]
,即继承前一个奇数项的最大交替和ou[i-1]
;或者选择包含nums[i-1]
,即前一个奇数项的最大交替和ji[i-1]
减去nums[i-1]
。
这个方程表示,以nums[i-1]
结尾的最大交替和的奇数项ji[i]
,可以选择不包含nums[i-1]
,即继承前一个偶数项的最大交替和ji[i-1]
;或者选择包含nums[i-1]
,即前一个偶数项的最大交替和ou[i-1]
加上nums[i-1]
。
通过不断更新ou[i]
和ji[i]
,最终可以得到以nums[n-1]
结尾的最大交替和的偶数项ou[n]
和奇数项ji[n]
,其中n
是nums
的大小。
最后,返回max(ou[n], ji[n])
作为最大交替和的结果。
class Solution {
public:
long long maxAlternatingSum(vector<int>& nums) {
int n=nums.size();
if(n == 1) return nums[0];
vector<long long> ou(n+1),ji(n+1);
for(int i=1;i<=n;i++){
ou[i]=max(ou[i-1],ji[i-1]-nums[i-1]);
ji[i]=max(ji[i-1],ou[i-1]+nums[i-1]);
}
return max(ou[n],ji[n]);
}
};