关于最大和的子数组的两个问题

文章介绍了如何使用动态规划解决两个数组问题:1.找到数组的子数组最大和;2.返回长度最长的最大和子数组。对于第一个问题,采用动态规划的思路,通过dp[i]=max(dp[i-1]+a[i],a[i])计算。第二个问题中,通过start和end确定检测区间,不断更新局部最大值和返回区间,以找到最长的最大和子数组。
摘要由CSDN通过智能技术生成

第一个问题是求一个数组的子数组的最大和:

这道题目比较简单,可作为第二道题的基准。

使用动态规划来做。

dp[i - 1] = max(dp[i - 1] + a[i],a[i])

代码如下

#include <iostream>
#include <algorithm>
using namespace std;

class Solution{
public:
    int FindGreatestSumOfSubArray(vector<int> array){
        vector<int> vec(array.size(),0);
        int maxnumber = array[0];
        vec[0] = array[0];
        if(array.size() == 1) return array[0];
        for(int i = 1;i < array.size();i ++){
            vec[i] = max(vec[i - 1] + array[i],array[i]);
            if(vec[i] > maxnumber) maxnumber = vec[i];
        }
        return maxnumber;
    }
};

第二个问题是需要返回长度最长的最大和子数组:

使用一个start,end来确定一个检测区间,一旦有元素值大于前面检测区的最大值加上它自己的话,拿么就更新检测区到这个元素,将这个元素与前面所有元素分割开来,因为要想获得最大值,这个元素不可能和前面的元素组成数组。总的来说就是这个元素嫌前面相邻的队友,自己单干都比与他们合作的数值大。

为了弄明白这道题目:

首先,要想明白一个问题:

假设有一个检测区间内的局部最大值,其下标为i,那么i一定小于等于end(注意元素值可能为正可能为负)。并且当前检测区域的局部最大长度子数组一定为start到i。 我们可以把这个区间叫做局部最大区间,这个最大值叫做局部最大值(还有一个全局最大值,即问题一求的)

接下来:

由于end一直向后移动,那么局部最大值肯能会更新。那么我们在局部最大值更新时让它与全局最大值作比较,有三种情况:

  1. 若它比全局最大值小,就不用管。

  1. 若它比全局最大值大,则这个局部最大区间就是现在的全局最大区间了,那么把返回区间等于上这个全局最大区间就行了。

  1. 若它与全局最大值相等,那就再比较局部最大区间与全局最大区间的长度,那个长,那个就是全局最大区间(题目要求最长子数组)。

所以:

使用一个rstart,rend来确定一个返回区间:

  1. 一旦在检测区间内发现了最大值,就把自己更新到与检测区间相同。

  1. 因为要求最大长度,所以一旦在检测区间发现了等于当前最大值的值,并且检测区间的长度要大于当前返回区间的长度,则更新返回区间与检测区间相同。

代码如下:

class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param array int整型vector 
     * @return int整型vector
     */
    vector<int> FindGreatestSumOfSubArray(vector<int>& array) {
        if(array.size() <= 1) return array;
        vector<int> dp(array.size(),0);
        int maxNumber = array[0];
        dp[0] = array[0];
        int start = 0;
        int end = 0;
        int rstart = 0;
        int rend = 0;
        for(int i = 1;i < array.size();i ++){
            //end指向当前元素
            end ++;
            //转移方程
            dp[i] = max(dp[i - 1] + array[i],array[i]);
            //Start将当前元素与之前数组分割开来,确定一个新的检测区域
            if(array[i] > dp[i - 1] + array[i]){
                start = end;
            }
            //检测区间内出现更大的值时,记录最大值,同时更新返回区间与检测区间相同
            if(dp[i] > maxNumber){
                maxNumber = dp[i];
                rstart = start;
                rend = end;
            }
            //检测区间内再次出现最大值,若长度比现在的返回区间要长,则更新返回区间
            else if(dp[i] == maxNumber && (end - start) > (rend - rstart)){
                rstart = start;
                rend = end;
            }
        }
        //返回返回区间即可
        vector<int> res;
        for(int i = rstart;i <= rend;i ++)
        {
            res.push_back(array[i]);
        }
        return res;
    }
};

新手学习中,记录与分享我刷题的一些想法。大家请请多指正。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值