LeetCode123—Best Time to Buy and Sell Stock III

LeetCode123—Best Time to Buy and Sell Stock III

股票买卖三兄弟之三

原题

Say you have an array for which the ith element is the price of a given stock on day i.

Design an algorithm to find the maximum profit. You may complete at most two transactions.

最多两次交易。

分析1

一种解法就是,把prices分为两半,0~ii+1~prices.size()-1,在这种情况下,求出前i天的全局最优dp1[i],和后prices.size()-i天的全局最优dp2[i],然后相加即可。这里的i要进行一次遍历,因此算法总体的复杂度是 O(n2)

分析2

参考:http://blog.csdn.net/linhuanmars/article/details/23236995
也是提供局部最优和全局最优的解法。
令:
local[i][j] 是在第i天卖出且经历j次交易的最大利益;
global[i][j] 是前i天经历j次交易的最大利益;

那么我们最终想要的结果就是 global[prices.size()1][2]
动归方程如下:
diff=prices[i+1]prices[i](1)
局部最优的动归方程:
local[i+1][j+1]=max(local[i][j+1]+diff,global[i][j]+max(diff,0))(2)

这里简单的解释一下式(2)

1.local[i][j+1]表示有j+1次交易,且最后一次卖出是在第i天;
2.global[i][j]表示有j次交易,且这j次交易是在前i天完成;
3.现在求local[i+1][j+1],也就是说最后一次卖出必须在第i+1天

从1.来看,对应在第i天卖出,现在已经满足了j+1次交易了,那么如果要强行在i+1天卖出,则要把在第i天操作的这个卖出抵消掉(考虑diff=prices[i+1]-prices[i])。

从2.来看,global[i][j]相较于j+1次交易要少一次交易,由于这次卖出必须在第i+1天进行,由于前i天已经是全局最优,那么最后这一次买卖,只有两种情况:
a)第i天买入,第i+1天卖出
b)第i+1天买入,第i+1天卖出
上述两种情况就取决于第i+1天的价格是否比第i天的价格高了,没人愿意做亏本的买卖嘛,至少也是要保本。

全局最优方程可以这样写:
global[i+1][j+1]=max(global[i][j+1],local[i+1][j+1])(3)

这个相较于局部最优就好理解多了。

代码2

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int len = prices.size();
        if (0 == len)
            return 0;
        vector<vector<int>>local(len + 1, vector<int>(3));//局部最优
        vector<vector<int>>global(len + 1, vector<int>(3));//全局最优
        for (int i = 0; i <len-1 ; i++)
        {
            int diff = prices[i + 1] - prices[i];
            for (int j = 0; j < 2; j++)
            {
                local[i + 1][j + 1] = max(local[i][j + 1] + diff, global[i][j] + max(diff, 0));
                global[i + 1][j+1] = max(global[i][j+1], local[i + 1][j+1]);
            }
        }
        return global[len-1][2];
    }
};

分析3

这里还有一个技巧就是降维,二维变一维,也就是说由于求解第i+1行j+1列的数据时,用到上一行第i行第j+1列,以及第i行第j列的数据。因为天数i是循环递增的,所以每次循环我们可以用一维数组保存当前行第i行的数据。又由于只能保存一行数据,我们在更新第i行第j列的数据时,需要用到上一行上一列[i][j]的数据,而这个数据又会被当前行上一列的数据覆盖[i][j-1],因此对于变量j来说,我们只能从后往前迭代。

代码3

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        if(0==prices.size())
            return 0;
        vector<int>local(3);//局部最优
        vector<int>global(3);//全局最优
        for (int i = 0; i < prices.size()-1; i++)
        {
            int diff = prices[i + 1] - prices[i];
            for (int j = 1; j >= 0; j--)//从后往前
            {
                local[j + 1] = max(local[j+1]+diff,global[j]+max(diff,0));
                global[j + 1] = max(global[j + 1], local[j + 1]);
            }
        }
        return global[2];
    }
};
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值