开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第3天,点击查看活动详情
环形子数组最大和(单串动态规划)
题目描述
给定一个长度为 n 的环形整数数组 nums ,返回 nums 的非空 子数组 的最大可能和
求区间最大和解决首尾不相接
求区间最小和,sum-区间最小和解决首尾相接部分
思路分析
- 情况一:只有一段子段(可能包含首元素或者尾元素)
- 情况二:有两段子段(同时包含首元素和尾元素)
- 两种情况都算出,比较结果,得出最大值
- 情况一:等价于“非循环数组最大子段和”
- 情况二:首先考虑0开头的一段,再考虑以最后元素结尾的一段,将两个子段最大和相加,求此情况最大,即求区间最小和,sum-区间最小和,剩余就是首尾相接部分的最大和。
代码实现
public:
int maxSubarraySumCircular(vector<int>& nums) {
//非空子数组包括单个元素
//作为非环形处理:
//区间最大large
//区间最小small,总和-区间最小=相接部分最大?区间最大
int len=nums.size(),ans=0,sum=nums[0];
vector<int>large(len),small(len);
small[0]=large[0]=nums[0];
//数组长度是1,或者空数组单独考虑
if(len==1) return nums[0];
//正常求非循环数组最大
for(int i=1;i<len;i++){
sum+=nums[i];
large[i]=max(large[i-1]+nums[i],nums[i]);
}
//最小,不包括首尾元素,所以i限制到len-1,即倒数第二个
for(int i=1;i<len-1;i++)
small[i]=min(small[i-1]+nums[i],nums[i]);
int maxx=*max_element(large.begin(),large.end());
int minn=*min_element(small.begin(),small.end());
return max(maxx,sum-minn);
}
};
知识点
*max_element(v.begin(),v.end())
//输出vector数组最大值,数组从小到大排序,输出最后面的值
*min_element(v.begin(),v.end())
//输出vector数组最小值,数组从小到大排序,输出最前面的值
*min_element(arr, arr + 4)
//普通定长数组输出最小值