从零开始的leetcode:股票问题

股票问题

任务描述

大意就是有个数组 prices 代表每天股票价格,共 n 天,计算能获取的最大利润。
规则:总共能交易 i(i = 1,2,inf) 次(每次交易完成有 j 天的冷却时间,每次交易扣除 k 块钱手续费)

解决思路

动态规划三步曲:

  1. 定义数组的含义

    这一步一般和题目要求有关。假设 dp[a][b][c]代表第 a 天,总共允许交易 b 次,且此时手里有没有股票的状态为 c,则 dp[n-1][i][0]代表今天最后一天,总共能交易 i 次的最大利润。

  2. 状态方程(参考)

递推公式:
dp[a][b][0] = max(dp[a-1][b][0], dp[a-1][b][1] + prices[a]) 
/*					无事				卖					    */
/*共a天,能买b次,手里没股票,两种情况*/
/*1:今天什么都没干,即和昨天情况没区别*/
/*2:今天把股票卖了,昨天肯定手里有票,利润加今天价格(昨天买了股票利润就减掉了昨天价格)*/   
dp[a][b][1] = max(dp[a-1][b][1], dp[a-1][b-1][0] - prices[a])
/*					无事				买					    */
/*共a天,能买b次,手里有股票,两种情况*/
/*1:今天什么都没干,即和昨天情况没区别*/
/*2:今天买股票,昨天肯定手里无票,利润减今天价格,到今天为止能买b次,昨天肯定为b-1次)*/  
  1. 初始值
基础情况:
dp[-1][b][0] = 0 //-1代表还没开始
dp[-1][b][1] = -Infinity //没开始不可能有股票在手
dp[a][0][0] = 0 //共a天,不能买,利润0
dp[a][0][1] = -Infinity //不可能

leetcode题解

leetcode-121

只买一次

输入: [7,1,5,3,6,4]
输出: 5(6-1)

状态方程:

dp[a][1][0] = max(dp[a-1][1][0], dp[a-1][1][1] + prices[a])
dp[a][1][1] = max(dp[a-1][1][1], dp[a-1][0][0] - prices[a]) 
            = max(dp[a-1][1][1], -prices[a])

题解:

class Solution {
public: 
    int maxProfit(vector<int>& prices) {
    int dp_a10 = 0, dp_a11 = INT_MIN  ,n=prices.capacity();
        
    for (int i=0;i<n;i++) {
        dp_a10 = max(dp_a10, dp_a11 + prices[i]);
        dp_a11 = max(dp_a11, -prices[i]);
    }
        
    return dp_a10;
    }
};

leetcode-122

买无限次

输入: [7,1,5,3,6,4]
输出: 7(5-1+6-3)

状态方程:

dp[a][inf][0] = max(dp[a-1][inf][0], dp[a-1][inf][1] + price)
dp[a][inf][1] = max(dp[a-1][inf][1], dp[a-1][inf][0] - price)

题解:

class Solution {
public: 
    int maxProfit(vector<int>& prices) {
    int dp_a0 = 0, dp_a1 = INT_MIN  ,n=prices.capacity();
        
    for (int i=0;i<n;i++) {
    	int temp = dp_a0;//dp_a0和dp_a1相互影响,为了得到上一天的情况
        dp_a0 = max(dp_a0, dp_a1 + prices[i]);
        dp_a1 = max(dp_a1, temp-prices[i]);
    }
        
    return dp_a0;
    }
};

leetcode-123

买两次

输入: [3,3,5,0,0,3,1,4]
输出: 6(3-0+4-1)

状态方程:

dp[a][2][0] = max(dp[a-1][2][0], dp[a-1][2][1] + price)
dp[a][2][1] = max(dp[a-1][2][1], dp[a-1][1][0] - price)
dp[a][1][0] = max(dp[a-1][1][0], dp[a-1][1][1] + prices[a])
dp[a][1][1] = max(dp[a-1][1][1], -prices[a])

题解:

class Solution {
public: 
    int maxProfit(vector<int>& prices) {
    int dp_a20 = 0, dp_a10 = 0, dp_a21 = INT_MIN, dp_a11 = INT_MIN, n=prices.capacity();
        
    for (int i=0;i<n;i++) {
        dp_a20 = max(dp_a20, dp_a21 + prices[i]);
        dp_a21 = max(dp_a21, dp_a10-prices[i]);
        dp_a10 = max(dp_a10, dp_a11 + prices[i]);
        dp_a11 = max(dp_a11, -prices[i]);
    }
        
    return dp_a20;
    }
};

leetcode-188

买 b 次

状态方程

dp[a][b][0] = max(dp[a-1][b][0], dp[a-1][b][1] + price)
dp[a][b][1] = max(dp[a-1][b][1], dp[a-1][b-1][0] - price)

题解

class Solution {
public:
    int maxProfit(int b, vector<int>& prices) {
    int n = prices.capacity();
    if (b >= n >> 1) {
        int dp_a0 = 0, dp_a1 = INT_MIN;

        for (int i=0;i<n;i++) {
            int temp = dp_a0;//dp_a0和dp_a1相互影响,为了得到上一天的情况
            dp_a0 = max(dp_a0, dp_a1 + prices[i]);
            dp_a1 = max(dp_a1, temp-prices[i]);
        }

        return dp_a0;
    }
        vector<int> dp_ab0(b + 1,0) ;
        vector<int> dp_ab1(b + 1, INT_MIN);
        
    for (int i=0;i<n;i++) {
         for (int j = b; j > 0; j--){
         	dp_ab0[j] = max(dp_ab0[j], dp_ab1[j] + prices[i]);
         	dp_ab1[j] = max(dp_ab1[j], dp_ab0[j - 1] - prices[i]);
         }
    }
        
    return dp_ab0[b];
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值