最大和连续子序列系列

一. 简单题目(求数组中最大和连续子序列)

    思路:(前i个数的和+当前数)是否大于当前数,大于则为前i个数的和+当前数,否则为当前数

   

//
//  main.cpp
//  最大连续子序列和
//
//  Created by jzc on 2018/4/24.
//  Copyright © 2018年 jzc. All rights reserved.
//

#include <iostream>
using namespace std;
int main() {
    int a[9] = {-2,1,-3,4,-1,2,1,-5,4};
    int sum[9];
    sum[0] = a[0];
    int k ;
    for(int i =1;i<9;i++){
        if(sum[i-1]+a[i]>a[i])
            sum[i] = sum[i-1]+a[i];
        else
        {
            sum[i] = a[i];
            k = i;
        }
    }
    int max = a[0];
    for(int i =0;i<9;i++)
    {
        if(sum[i]>max)
        {
            max = sum[i];
        }
    }
    cout<<"子序列最大和:"<<max<<endl;
    int count =0;
    cout<<"子序列为:";
    while(count!=max)
    {
        cout<<a[k]<<" ";
        count+=a[k];
        k++;
    }
    cout<<endl;
    return 0;
}

二. 进阶连续子序列:

   leetcode121: 题目大概意思是:一串数组,第i天对应的股票为a[i], 第i天买股票,第j天卖股票,收益为a[j]-a[i](卖股票的日子必须在买股票的日子之后),找到最大收益。

  注意:收益只能是非负的。

  

//
//  main.cpp
//  leetcode121
//
//  Created by jzc on 2018/4/30.
//  Copyright © 2018年 jzc. All rights reserved.
// 最大连续子序列变形
//

#include <iostream>
using namespace std;
int main() {
    int a[10]={1,2};
    int sum = a[1]-a[0];
    int max = 0;
    if(sum>max)
    max = sum;
    for(int i=1;i<1;i++)
    {
        if(sum+a[i+1]-a[i]>(a[i+1]-a[i]))
        sum=sum+a[i+1]-a[i];
        else
        sum =a[i+1]-a[i] ;
        if(sum>max)
        max = sum;
    }
    cout<<max<<endl;
    return  0;
}

三.再次进阶连续子序列

   基于二,不限制交易次数,进行很多次交易,每次交易只能等上一次交易结束之后,才能开始。收益必须非负。

  思路:既然不限次数,那只要将相邻的两个求差,差值如果大于0,就累加起来,最终的累加值就是最大收益

 

int maxProfit(int* prices, int pricesSize) {
    int sum = 0;
    for(int i =1;i<pricesSize;i++)
    {
        if(prices[i]>prices[i-1])
            sum+=(prices[i]-prices[i-1]);
    }
    return sum;
    
}

 

四. 再次er进阶连续子序列:

    leetcode123, 题目大概意思和上面差不多,同样是第i天对应的股票为a[i], 第i天买股票,第j天卖股票,收益为a[j]-a[i](卖股票的日子必须在买股票的日子之后)。找到最大的收益。收益不能为负。

   增加了条件:可以进行最多两次交易(两次或一次):比如可以在第一天买股票,第三天卖股票,第五天买股票,第六天卖股票。规定:第二次交易必须要再第一次买卖完之后才可以开始

   思路:其实上道题,我的想法还是基于连续子序列的方法。对于这道题我第一的想法是划分:分成第一次和第二次交易,然后最后将两次划分结果求的最大收益加起来就是这道题的解。如果划分成了两段,从第i天划分,第一段是求前i天的最大收益,后一段是求后i天的最大收益。如果我还是按照上题,对每一段求一个最大和连续子序列。。显然复杂度很高。有没有更好的求法,显然是有这样的规律:

     对于第i天a[i]要卖掉股票来说,要找一个x,使得a[i]-x是前i天的最大收益,那么我们只要找到最小的x,这个最小的x就是min{a[0].....a[i-1]}。同理如果找后i天的最大收益,就倒着扫描数组,找最大的a[i],是的a[i]-x 最大。

   具体代码如下:

   

int maxProfit(int* prices, int pricesSize) {
    int *a=(int *)malloc(sizeof(int)*pricesSize);
    a[0] = 0;
    int max = 0;
    int minprices = prices[0];
    a[0]=0;
    for(int i =1;i<pricesSize;i++)
    {
          if(prices[i]-minprices>max)
              max = prices[i]-minprices;
          a[i] = max;
          if(prices[i]<minprices)
              minprices = prices[i];
    }
    int maxprices = prices[pricesSize-1];
    max=0;  
    int sum=0;
    for(int i =pricesSize-2;i>=0;i--)
    {
        if(maxprices-prices[i]>max)
            max = maxprices-prices[i];
        if(i>0)
        {
            if(max+a[i-1]>sum)
                sum = max+a[i-1];
        }
        else
        {
            if(max>sum)
                sum = max;
        }
        if(prices[i]>maxprices)
            maxprices = prices[i];
    }
    return sum;
}

 

posted @ 2018-05-01 20:47  Cheney_1016  阅读(509)  评论(0编辑  收藏  举报