算法:买卖股票最佳时机(c++)

买卖股票相关问题:

1,只能买卖一次:

假设有一个数组,它的第i个元素是一支给定的股票在第i天的价格。
如果你最多只允许完成一次交易,设计一个算法来找出最大利润。

例如:[3,4,5,1,9]
输出:8
解释:第四天买入,第五天卖出

原理:为了减少复杂度,这里用峰谷的方法遍历
在第一个不亏损的日子买入,然后比较,如果后一天不卖是亏损还是接着赚。
亏损就放弃这一段,从下一个日子开始继续分析
接着赚就不放弃。
【说实话我觉着难点在怎么记这个开始和结束的日子,我还试了一下,挺麻烦的】
c++实现代码如下:

int main()
{
    int array[5] = {1,2,5,4,3};
    int max = 0;
    int num =0;
    for (int i = 0; i < sizeof(array)/sizeof(array[0]) - 1; i++)
    {
        num = num + (array[i + 1] - array[i]);
        if (num < 0)
        {
            num = 0;
            continue;
        }
        if (max < num)
        {
            max = num;
        }
    }
    if (max == 0)
    {
        printf("别买了吧就\n");
    }
    else
    {
        printf("能赚%d块钱",max);
    }
}

2,可以无限次买卖
【其实这个在第三个,但我觉着它比第三个简单点……甚至比第一个简单】

给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。
你可以尽可能地完成更多的交易(多次买卖一支股票)。
注意:你不能同时参与多笔交易

例;
输入:【1,2,3,5,2】
输入:4

原理非常简单:比较相邻两次的值,能赚就买,会亏就不买
代码如下:

int main()
{
    int array[5] = {1,2,5,4,3};
    int max = 0;
    int num =0;
    for (int i = 0; i < sizeof(array)/sizeof(array[0]) - 1; i++)
    {
        if (array[i + 1] > array[i])
        {
            max += array[i + 1] - array[i];
        }
    }
    if (max == 0)
    {
        printf("别买了吧就\n");
    }
    else
    {
        printf("能赚%d块钱",max);
    }
}

3,只限两次买卖:

给定一个数组,它的第 i 个元素是一支给定的股票在第 i 天的价格。

设计一个算法来计算你所能获取的最大利润。你最多可以完成 两笔 交易。

注意: 你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。

示例 1:

输入: [3,3,5,0,0,3,1,4]
输出: 6
解释: 在第 4 天(股票价格 = 0)的时候买入,在第 6 天(股票价格 = 3)的时候卖出,这笔交易所能获得利润 = 3-0 = 3 。
随后,在第 7 天(股票价格 = 1)的时候买入,在第 8 天 (股票价格 = 4)的时候卖出,这笔交易所能获得利润 = 4-1 = 3 。

这部分借鉴的这篇文章:https://blog.csdn.net/lzz_zz/article/details/102860884
看这段的时候满脑子,妈妈这段代码好牛逼……
嗯……把大佬的思路展开一下!
【为了做这题我还去捡了一下动态规划】
简单的说,其实可以把两次买卖规划成这样:
第一天:买/卖/维持
第二天:买/卖/维持
……
每个结点有自己的值(股票价格)
其实就是一个四层的树
不过也有特别的地方,比如如果第一天没买,第二天就不可能卖,不过这点我们后说。
把每个结点动态规划出来:
【前面是不操作,后面是操作】
s1[i] = max(s1[i-1],-price)
s2[i] = max(s2[i-1],s1[i-1]+price)
s3[i] = max(s3[i-1],s2[i-1]-price)
s4[i] = max(s4[i-1],s3[i-1]+price)
动态规划是一种自底向上的结构——但是这里的循环排序是s4,s3,s2,s1这样的,为什么呢?
因为,开始时设定的s1为负无穷,s3为负无穷,这样在位置为1的时候前三者都处于极限状态,只有s1能够获得实际数值——而s1能影响下个位置的s2,事实上,这还是从s1往上讨论的。
而s2的判断方式和第一问,一次买卖的想法类似。
实现代码如下:

#include <iostream>
#include <stdlib.h>
int max(int a, int b)
{
    if (a > b)
        return a;
    else
        return b;
}
int main()
{
    int array[6] = {3,2,5,4,3,6};
    int s1 = INT8_MIN, s2 = 0, s3 = INT8_MIN, s4 = 0;
    for (int i = 0; i < sizeof(array) / sizeof(array[0]); i++)
    {
        s4 = max(s4,s3+array[i]);
        s3 = max(s3, s2 - array[i]);
        s2 = max(s2, s1 + array[i]);
        s1 = max(s1, -array[i]);
    }
    printf("%d",s4);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值