动态规划股票交易

Posted 桃陉

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了动态规划股票交易相关的知识,希望对你有一定的参考价值。


1.买卖股票的最佳时机

1.1 题目

给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。

你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。

返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回 0 。

示例 1:
输入:[7,1,5,3,6,4]
输出:5
解释:在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。
注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格;同时,你不能在买入前卖出股票。


示例 2:
输入:prices = [7,6,4,3,1]
输出:0
解释:在这种情况下, 没有交易完成, 所以最大利润为 0。

提示:

∙ \\bullet 1 <= prices.length <= 105
∙ \\bullet 0 <= prices[i] <= 104

来源:力扣(LeetCode)
链接:题目来源

1.2 分析

∙ \\bullet 我们只需要进行一次交易,即买入一次卖出一次。当数组中只有一个数字时返回0,当数组中数字倒序时无法买卖返回0。

∙ \\bullet 在编写时我们需要一个变量ans来指向第一个数字(ans表示买入的时刻,我们要保证它尽量的小),然后从下标为1的地方遍历数组,当遍历元素小于ans时,我们就更新ans。每次都将最终返回结果res与当前元素减去ans的值进行比较,取其中较大的值。
r e s = m a x ( r e s , p r i c e s [ i ] − a n s ) ; res = max(res,prices[i]-ans); res=max(res,prices[i]ans);

1.3 代码

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int n=prices.size();
        int ans=prices[0],res=0;
        for(int i=1;i<n;i++)
        {
            if(prices[i]<ans) ans=prices[i];
            res=max(res,prices[i]-ans);  
        }
        return res;

    }
};

2.买卖股票的最佳时机 II

2.1 题目

给定一个数组 prices ,其中 prices[i] 是一支给定股票第 i 天的价格。

设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易(多次买卖一支股票)。

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

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


示例 2:
输入: prices = [1,2,3,4,5]
输出: 4
解释: 在第 1 天(股票价格 = 1)的时候买入,在第 5 天 (股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5-1 = 4 。
注意你不能在第 1 天和第 2 天接连购买股票,之后再将它们卖出。因为这样属于同时参与了多笔交易,你必须在再次购买前出售掉之前的股票。


示例 3:
输入: prices = [7,6,4,3,1]
输出: 0
解释: 在这种情况下, 没有交易完成, 所以最大利润为 0。

提示:

∙ \\bullet 1 <= prices.length <= 3 * 104
∙ \\bullet 0 <= prices[i] <= 104

来源:力扣(LeetCode)
链接:题目来源

2.2 分析

∙ \\bullet 我们注意到与第一问不同,这次可以多次的买入与卖出,然后找到最大的利润。

∙ \\bullet 在这里我们需要设置两个状态,dp[i][0] 表示当前不持有股票,dp[i][1] 表示当前持有股票。那么最后返回dp[n-1][0]。

∙ \\bullet 对于dp[i][0] 来说,可能昨天也不持有(dp[i-1][0])或者昨天持有今天卖出(dp[i-1][1]+prices[i]),取两者的较大值。
d p [ i − 1 ] [ 0 ] = m a x ( d p [ i − 1 ] [ 0 ] , d p [ i − 1 ] [ 1 ] + p r i c e s [ i ] ) ; dp[i-1][0]=max(dp[i-1][0],dp[i-1][1]+prices[i]); dp[i1][0]=max(dp[i1][0],dp[i1][1]+prices[i]);

∙ \\bullet 对于dp[i][1] 来说,可能昨天也持有(dp[i-1][1])或者昨天不持有今天买入(dp[i-1][0]-prices[i]),取两者的较大值。
d p [ i − 1 ] [ 1 ] = m a x ( d p [ i − 1 ] [ 1 ] , d p [ i − 1 ] [ 0 ] − p r i c e s [ i ] ) ; dp[i-1][1]=max(dp[i-1][1],dp[i-1][0]-prices[i]); dp[i1][1]=max(dp[i1][1],dp[i1][0]prices[i]);

2.3 代码

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int n=prices.size();
        if(n==1) return 0;
        //dp[i][0]表示当前不持有股票,dp[i][1]表示当前持有股票
        vector<vector<int>>dp(n,vector<int>(2,0));
        dp[0][1]=-prices[0];
        for(int i=1;i<n;i++)
        {
            dp[i][0]=max(dp[i-1][0],dp[i-1][1]+prices[i]);
            dp[i][1]=max(dp[i-1][1],dp[i-1][0]-prices[i]);
        }
        return dp[n-1][0];
    }
};

3.最佳买卖股票时机含冷冻期

3.1 题目

给定一个整数数组,其中第 i 个元素代表了第 i 天的股票价格 。​

设计一个算法计算出最大利润。在满足以下约束条件下,你可以尽可能地完成更多的交易(多次买卖一支股票):

你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
卖出股票后,你无法在第二天买入股票 (即冷冻期为 1 天)。

示例:
输入: [1,2,3,0,2]
输出: 3
解释: 对应的交易状态为: [买入, 卖出, 冷冻期, 买入, 卖出]

来源:力扣(LeetCode)
链接:题目来源

3.2 分析

∙ \\bullet 本题相对于上一题增加了一个冷冻期,此时持有股票的状态得分成两部分,一个为今天持有股票且不卖出(dp[i][0]),一个为今天持有且今天卖出(明天为冷冻期) (dp[i][1])。不持有股票的状态不变(dp[i][2])。最后返回 max(dp[n-1][1],dp[n-1][2]);

∙ \\bullet 对于dp[i][0]来说,可能昨天也持有(dp[i-1][0])或者昨天不持有今天买入(dp[i-1][2]-prices[i]),取二者较大值。
d p [ i ] [ 0 ] = m a x ( d p [ i − 1 ] [ 0 ] , d p [ i − 1 ] [ 2 ] − p r i c e s [ i ] ) ; dp[i][0]=max(dp[i-1][0],dp[i-1][2]-prices[i]); dp[i][0]=max(dp[i1][0],dp[i1][2]prices[i]);

∙ \\bullet 对于dp[i][1]来说,昨天必须持有股票今天才可以卖出。
d p [ i ] [ 1 ] = d p [ i − 1 ] [ 0 ] + p r i c e s [ i ] ; dp[i][1]=dp[i-1][0]+prices[i]; dp[i][1]=dp[i1][0]+prices[i];

∙ \\bullet 对于dp[i][2]来说,可能昨天也不持有股票(dp[i-1][2])或者昨天持有并卖出(dp[i-1][1]),取二者较大值。
d p [ i ] [ 2 ] = m a x ( d p [ i − 1 ] [ 2 ] , d p [ i − 1 ] [ 1 ] ) ; dp[i][2]=max(dp[i-1][2],dp[i-1][1]); dp[i][2]=max(dp[i1][2],dp[i1][1]);

3.3 代码

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int n=prices.size();
        if(n==0) return 0;
        /*
        dp[i][0] 表示当天持有一支股票
        dp[i][1] 表示当天卖出股票(意思就是第i+1天是冷冻期)
        dp[i][2] 表示当天不持有股票
        */
        vector<vector<int>>dp(n,vector<int>(3,0));
        dp[0][0]=-prices[0];

        for(int i=1;i<n;i++)
        {
            dp[i][0]= max(dp[i-1][0],dp[i-1][2]-prices[i]); //可能是昨天就持有或者昨天不持有今天买入
            dp[i][1]=dp[i-1][0]+prices[i]; //昨天必须持有今天才可以卖出
            dp[i][2]=max(dp[i-1][2],dp[i-1][1]);
        }
        return max(dp[n-1][1],dp[n-1][2]);
    }
};

4.买卖股票的最佳时机含手续费

4.1 题目

给定一个整数数组 prices,其中第 i 个元素代表了第 i 天的股票价格 ;整数 fee 代表了交易股票的手续费用。

你可以无限次地完成交易,但是你每笔交易都需要付手续费。如果你已经购买了一个股票,在卖出它之前你就不能再继续购买股票了。

返回获得利润的最大值。

注意:这里的一笔交易指买入持有并卖出股票的整个过程,每笔交易你只需要为支付一次手续费。

示例 1:
输入:prices = [1, 3, 2, 8, 4, 9], fee = 2
输出:8
解释:能够达到的最大利润:
在此处买入 prices[0] = 1
在此处卖出 prices[3] = 8
在此处买入 prices[4] = 4
在此处卖出 prices[5] = 9
总利润: ((8 - 1) - 2) + ((9 - 4) - 2) = 8


示例 2:
输入:prices = [1,3,7,5,10,3], fee = 3
输出:6

提示:

∙ \\bullet 1 <= prices.length <= 5 * 104
∙ \\bullet 1 <= prices[i] < 5 * 104
∙ \\bullet 0 <= fee < 5 * 104

来源:力扣(LeetCode)
链接:题目来源

4.2 分析

∙ \\bullet 本题其实与第二题十分相似,只是在卖出的基础上添加了小费,所以我们只需要在每次卖出的基础上补充小费即可。

∙ \\bullet 同样设置两个状态,dp[i][0] 表示当前不持有股票,dp[i][1] 表示当前持有股票。那么最后返回dp[n-1][0]。

∙ \\bullet dp[i][1] 不变,对于dp[i][0]加上小费fee。
d p [ i ] [ 0 ] = m a x ( d p [ i − 1 ] [ 0 ] , d p [ i − 1 ] [ 1 ] + p r i c e s [ i ] − f e e ) ; dp[i][0]=max(dp[i-1][0],dp[i-1][1]+prices[i]-fee); dp[i][0]=max(dp[i1][0],dp[i1][1]+prices[i]fee);

4.3 代码

class Solution {
public:
    int maxProfit(vector<int>& prices, int fee) {
        int n=prices.size();
        if(n==1) return 0;
        //dp[i][0]表示当前不持有股票,dp[i][1]表示当前持有股票
        vector<vector<int>>dp(n,vector<int>(2,0));
        dp[0][1]=-prices[0];
        for(int i=1;i<n;i++)
        {
            dp[i][0]=max(dp[i-1][0],dp[i-1][1]+prices[i]-fee);
            dp[i][1]=max(dp[i-1][1],dp[i-1][0]-prices[i]);
        }
        return dp[n-1][492,动态规划和贪心算法解买卖股票的最佳时机 II

Leetcode No.188 买卖股票的最佳时机 IV(动态规划)

Leetcode No.188 买卖股票的最佳时机 IV(动态规划)

leetcode-买卖股票的最佳时机(动态规划)

动态规划买卖股票的最佳时机II

LeetCode-动态规划买卖股票的最佳时机