0
点赞
收藏
分享

微信扫一扫

C++入门教程(22)连续区间最大和问题(股票最大收益)

天涯学馆 2022-03-30 阅读 99
c++

最近看到一个连续区间最大和的问题,很感兴趣,主要是因为这个问题可以用于求一段时间内的股票最大收益问题。

而一段连续的数字就是每一时刻股票的波动情况

以某指数为例:

下方红绿即为每一时段的变化,对应上方是当前时段对应的价格,在什么时间段买入和卖出才能获取最大的收益呢?我首先想到的就是在最低点买入,最高点卖出了,可以通过遍历求出前N项和,得到股票最高点和最低点的时刻,然后进行交易,最低点买入最高点卖出。

但是这样处理有一个问题,就是最高点可能提前于最低点出现,也就是说通过上述方法得到的结果可能为最小值,以至于亏了最多的钱,org 。

正确的做法应该是这样的,任意时刻作为结束点,我们都能从这个点往前找到最佳买入时机,以获取最大收益,这样我们可以算出每个时刻卖出能获得的最大收益,然后维护一个最大收益值的变量就可以了。思路有了我们实现起来就方便了

 

         当前时刻能获取的最大收益 = 当前时刻的前N项和 - 前面最低点的qianN项和 

int getMaxNum1(int *A,int len)
{
    //维护一个最低点
    int sumMin = 0;
    //前n项和
    int sum = 0;
    //最终结果
    int ans = 0;
    //动态算出每个点的最大收益
    int dp = 0;
    for (int i = 0; i < len; ++i)
    {
        //累加前n项和
        sum = sum + A[i];
        sumMin = min(sum,sumMin);
        
        //算出当前点能获得的最大收益
        dp = max(dp, sum - sumMin);    //以Arr[i]结尾的区间最大值
        ans = max(ans, dp);
    }
    return ans;
}

在网上看到的一些代码不是很好理解,这里也参考进来,完整代码:


#include <iostream>
using namespace std;

//int arr[10] = {8,-10,-8,11,20,-5,-19,11,38,-5};

int arr[10] = {1,2,3,4,5,-21,6,7,8};

//我自己的思路实现
int getMaxNum1(int *A,int len)
{
    //维护一个最低点
    int sumMin = 0;
    //前n项和
    int sum = 0;
    //最终结果
    int ans = 0;
    //动态算出每个点的最大收益
    int dp = 0;
    for (int i = 0; i < len; ++i)
    {
        //累加前n项和
        sum = sum + A[i];
        sumMin = min(sum,sumMin);
        
        //算出当前点能获得的最大收益
        dp = max(dp, sum - sumMin);    //以Arr[i]结尾的区间最大值
        ans = max(ans, dp);
    }
    return ans;
}

//网上搜到的代码,看起来不是很好理解
int getMaxNum2(int *A,int len)
{
    //动态算出每个点的最大收益
    int dp = 0;
    //最终结果
    int ans = 0;
    for (int i = 0; i < len; ++i)
    {
        //当前节点能获得的最大收益 如果当前节点之前的一个节点还在亏钱 则dp将更正为当前节点能挣的最多的钱
        dp = max(A[i], A[i] + dp);
        
        //比较每个节点能获得的最大利益 维护一个最大值
        ans = max(ans, dp);
    }
    
    return ans;
}


int main(int argc, const char * argv[]) {
    // insert code here...
    //std::cout << "Hello, World!\n";
    
    int maxNum2 = getMaxNum2(arr,10);
    cout<<"maxNum2 : "<<maxNum2 << endl;
    
    int maxNum1 = getMaxNum1(arr,10);
    cout<<"maxNum1 : "<<maxNum1 << endl;
    
    return 0;
}

运行:

maxNum2 : 56
maxNum1 : 56

可以看到两个函数实现都能得到同样的结果,但是个人感觉还是我实现的更容易理解。

前N项和表示了股票当前时刻的价格,维护一个最低点,表示最佳买入时机,对应的差价,就是当前时刻卖出能赚取的股票差价。理论联系实际,理解起来快多了,但是第二段代码读起来就晦涩难懂了很多。

另外要说的是,第一个想法也不是一点用没有,获得的最小值在可以双向购买的股票中是可以做空的,这样看来得到最小的值也有用,但是不在本命题的讨论范围,如果要问为啥,那就是大A不可以做空, ^_^

举报

相关推荐

0 条评论