子数组最大和问题

                                                         [博客为作者复习笔记]

解决方法:

Kadane算法

动态规划

滑动窗口

适用问题:

        适用于解决子数组最大和问题

核心思想:        

        拆解状态,构造转移过程(动态规划) 

        局部最优 与 全局最优 关系判断证明 (贪心)

算法思路推导:

        思路 1 :[动态规划+递推+贪心]

                要想知道最大和子数组。最简单的是暴力,那先分析这个方法。

                用左右边界状态存储数组和 Sum[Lenth][Lenth]

                    当前数组和 =除去最后元素的前缀数组和 +当前元素

                

                那优化一下。怎么求这个所有子数组的和构成的集合?

                让我们更方便用公式总结。

当前数组子数组和的集合 ={ 除去最后元素的前缀数组子数组和的集合+当前元素,当前元素}

                那怎么样将最大Sum,MaxSonSum求出来呢?

                一种巧妙的贪心递推       

               最大子数组和 = max(max(当前子数组和集合),最大子数组和)

    (维护DP表)当前子数组和集合 的 最大值 = 最大子数组和(非必要)

公式:

SonSum_{L\rightarrow R}= \left\{\begin{matrix} \, \, \, \, \, \, \, \ Elem_{R}\, \, \, \, \, \, \, \, \, \, \, \, \, \, \, \, \, \, \, \, \, \, \, \, \, \, \, \, \, \, \, \, \, \, \, \, \, \, \, \, \, \, \, \, \, \, \, \, \, \\ SonSum_{L\rightarrow (R-1)}+Elem_{R}\end{matrix}\right. 

SonSumSet_{\, \, L\rightarrow R} = set( \, \, \, \, SonSum_{L\rightarrow R} ()\, \, \, \, \, \, )

GolbalMaxSonSum = \max(\max(SonSumSet_{\, \, \, L\rightarrow R})\, \, \, \, ,\, \, \, \, GlobalMaxSonSum )

    

问题1:

MaxSonSum[l][r] =max(MaxSonSum[l][r-1]+Data[r],Data[r]) 你觉得他对吗?

            不,它不对。因为DP[l][r]>DP[l][r-1]不一定成立,没有这个单调性也就没有办法求全局最优因此你必须需要一个维护全局最优的数据 GlobalMaxSum

问题2:

Global只需要在最后赋值给DP[l][r]就可以了吗。

对于这个问题关键看你的DP结构是什么。

        如果你只是想要最终结果,完全可以用一个变量GlobalMaxSum来维护,因此也不需要,也没有DP表格,

        如果你要维护DP表以优化查询,那就要确保DP表是正确的。这时候就要确保每步保存局部最优。对每个DP进行GlobalMaxSum赋值。

        GlobalMaxSum能保证最终的全局解符合题意。那你要知道DP[l][r]是要靠前面的数据DP[l][r-1]来得到结果的。那DP[l][r-1]又是怎么求的?他也是需要一个GlobalMaxSum,或者说DP表,所以说这又是一个递推的问题。对此要在每一个DP[l][r]计算时都要为其取全局最优。递推保证过程严谨。而选择DP表还是GlobalMaxSum变量来维护就看具体需要了。

问题3:

DP表结构是什么样子 。      

        理解递推。这样说来我们就可以看出来DP的(边界)起点与终点了。起点是每一个

DP[i][i],终点是DP[i][R]

实际上,你观察后会发现每个DP[0][R]求值时只会用到同一行,也就是前缀最大子数组和,

也就是某些情况下可做些取舍:

伪代码:

  • 当查询次数较少可以计算尽量少的数据来求解,以保证效率

                     A:        (标准Kadane)

                 

GlobalMaxSum = max(GlobalMaxSum,max(CurrentSum+Data[n],Data[n]))

  

                     B:        (一维DP式Kadane)
                

GlobalMaxSum = max(GlobalMaxSum,max(DP[n-1]+Data[n],Data[n] ))

  • 当查询次数多且任意子数组时,可以维护二维DP表,以保证查询效率

                                (可查询DP实现Kadane)                

GlobalMaxSum = max(max(DP[l][r-1]+Data[r],Data[r]),GlobalMaxSum))

                                                DP[l][r] = GlobalMaxSum
  • 如果只是单边界变化的子数组时,可以维护一维DP表

                             可查询二维DP实现Kadane)                

GlobalMaxSum = max(max(DP[n-1]+Data[n],Data[n),GlobalMaxSum)

DP[n]= GlobalMaxSum

注意:每一行GlobalMaxSum都是要置零刷新的,因为每行都是独立的需要单独计算,互不依赖

       思路2  :[滑动窗口+剪枝]

      滑动窗口的核心就是利用窗口在拓展上的单调性以及窗口收缩的条件性

        

Kadnae

模版代码:

[不进行存储]

int kadane(const std::vector<int>& nums) {
    int max_current = nums[0];
    int max_global = nums[0];

    for (size_t i = 1; i < nums.size(); ++i) {
        max_current = std::max(nums[i], max_current + nums[i]);
        if (max_current > max_global) {
            max_global = max_current;
        }
    }
    return max_global;
}

训练指标:

        模版复习与优化 : 理解熟悉算法过程

        理解拓展性     :   理解背后的核心思想

        刷题提高应用性 :    提高对题目描述的敏感度

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值