(动态规划)最大和连续子序列-leetcode53. 最大子数组和9月11日练习,9月12日也练习了:)

input:  一个整数数组 A[],假设其长度为n

output:一个连续子数组的最大和 (int),answer

《算法设计与分析》黄宇(题目3.9):最大和连续子序列

给定一个由整数组成的序列nums[],请找出和最大的连续子序列。例如,nums={-2,11,-4,13,-5,-2},得到的结果应为20=11-4+13

1)你可以基于简单遍历数组元素,设计一个O(n^3)的算法

指针i从0-n扫描遍历,指针j从0-i扫描遍历

指针k从j-i扫描依次加和

int sumi[n];
int Max_i=nums[0];
for(int i=0;i<n;i++){
    int sumj[i];
    //求j-i使得和最大的那个j
         int max=sumj[0];
    for(int j=0;j<i;j++){
       for(int k=j;k<=i;k++){
         sumj[j]+=nums[k];
}//j->i的k循环

         if(sumj[j]>max) max=sumj[j];
  }//0->i的j循环
sumi[i]=max;
if(sumi[i]>Max_i) Max_i=sumi[i];    
}
return Max_i;

2)改进上述算法中的冗余计算,你可以得到一个基于遍历的O(n^2)的算法

3)基于分治策略,你可以设计一个O(nlogn)的算法

4)分析遍历算法中的冗余计算,你可以设计一个O(n)的算法

5)基于动态规划策略,你同样可以得到一个O(n)的动态规划算法


For this DP problem,I will try ‘SRTBOT’:

S-子问题定义

分析:输入为一个一维int序列,那么我假设子问题的规模也是一维的

try preffix[]:

       定义P(k)为A[1.....k]数组的最大和连续子序列的和(is an number)

R-子问题的递归关系

1.第A[i]个元素包含于P(i)最大子序列中:

       则P(i)=以元素A[i]结尾的所有连续子序列中,最大的那一个,即

P(i)=max{

                A[i],

                A[i]+A[i-1],

                A[i]+A[i-1]+A[i-2],

                .......,

                A[i]+A[i-1]+A[i-2].....+A[2]+A[1]

                }

    由于我们不知道是这i个序列中的具体哪一个,所以我们设一个指针j从1->i依次扫描,声明一个辅助变量S(i,j)[n][i],它是一个以i,j分别为维度的二维数组,一共n行,每行有i列(i=1,2,3,...n);

    设S(i,j)[i][j]=A[j]+....+A[i];

    固定i时,数组元素依次为:

      A[i]+A[i-1]+A[i-2].....+A[2]+A[1]、

      A[i]+A[i-1]+A[i-2].....+A[2]、

      A[i]+A[i-1]+.....+A[3]、

       .....、

      A[i-1]+A[i]、

      A[i].

     另外写一个函数int GetMaxArray(),用来求S(i,j)[][]数组里第i行的最大值,最大值记为Max_Sum_i;

//StartTag_j用来记录最长子序列的第一个下标
int GetMaxArray(& a[]){
//传入数组a[]
int len=sizeof(a);
int Max_Sum_i=a[0];
for(int k=0;k<len;k++){

  if(a[k]>Max_Sum_i)
    {Max_Sum_i=a[k];
     StartTag_j=k;}

}

return Max_Sum_i;
  }
2.第A[i]个元素不在P(i)中,则

P(i)=P(i-1)

3.综合1.2  ----> 得到整体的递归式

P(i)=max{  Max_Sum_i  ,  P(i-1) }

T-子问题调度的拓扑顺序

i从0一直增加到n

B-递归基

P(0)=A[0]

O-要求问题:goal

P(n)

T-时间分析


还未仔细调整的初步C++实现

int dp[n];//用来记录子问题的解
dp[0]=A[0];//B-asecase;

int S[n][];

for(int i=1;i<n;i++){
  for(int j=0;j<=i;j++){
     //此时i是固定的
     for(int k=j;k<=i;k++){ 
     S[i][j]+=A[k];
}//k的循环结束
  }//j的循环结束
      dp[i]=Max{dp[i-1],Get_Sum_Max(S[i][])};
       //此处可以用冒号表达式
    
    }

return dp[n];

/*以下是我第一次做leetcode53时总报错栈溢出的版本
也就是递归调用了maxSubArray函数
暂时不知道具体的问题出在哪里
之后我会回来解决
*/


class Solution {
public:
    int maxSubArray(vector<int>& nums) {
     //声明一个数组S来 储存子问题的解
     int n=sizeof(nums);
     int S[n];
     //定义递归基
     S[0]=nums[0];
     if(n==0) return 0;
     if(n==1) return nums[0];
     //
     for(int i=1;i<=n;i++){
        vector<int> copyi(nums.begin(),nums.begin()+i);
        vector<int> copyi1(nums.begin(),nums.begin()+i-1);
         
         if(maxSubArray(copyi)<maxSubArray(copyi1)+nums[i])
         {
             S[i]=S[i-1]+nums[i];
             }else{
             S[i]=S[i-1];

         }
     }
     return S[n-1];
    }
};

最后待修正代码

class Solution {

public:

    int maxSubArray(vector<int>& nums) {

     //声明一个数组S来 储存子问题的解

     

     long int n=sizeof(nums);

     long int dp[n];

     //定义递归基

     dp[0]=nums[0];

     if(n==0) return 0;

     if(n==1) return dp[0];

     //

     long int MAX_SUM=0;

     for(int i=1;i<n;i++){

        long int Sum_i=0;

        for(int j=i-1;j>=0;j--){

           

            Sum_i=Sum_i+nums[j];

        }    

        if(MAX_SUM<Sum_i)  MAX_SUM=Sum_i;

       

        dp[i]=max(MAX_SUM,dp[i-1]);

     }

     return dp[n-1];

    }

};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值