环形子数组最大和

126 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第3天,点击查看活动详情

环形子数组最大和(单串动态规划)

题目描述

给定一个长度为 n 的环形整数数组 nums ,返回 nums 的非空 子数组 的最大可能和 求区间最大和解决首尾不相接 求区间最小和,sum-区间最小和解决首尾相接部分

思路分析

  1. 情况一:只有一段子段(可能包含首元素或者尾元素)
  2. 情况二:有两段子段(同时包含首元素和尾元素)
  3. 两种情况都算出,比较结果,得出最大值
  • 情况一:等价于“非循环数组最大子段和”
  • 情况二:首先考虑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)
//普通定长数组输出最小值