dp-股票问题总结

最简单:

122. 买卖股票的最佳时机 II (能够买卖无数次)

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

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

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

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int n = prices.size();
        if (n <= 0) return 0;
        /*int dp[2][n];  就买入和卖出两个状态:
        memset(dp,0,sizeof(dp));
        dp[0][0] = -prices[0];
        dp[1][0] = 0;
        for(int i = 1; i < n; i++){
            dp[0][i] = max(dp[0][i-1],dp[1][i-1] - prices[i]);
            dp[1][i] = max(dp[0][i-1] + prices[i],dp[1][i-1]);
        }
        return dp[1][n-1]; */
    // 空间优化
int hold, sell; hold = -prices[0]; sell = 0; for (int i = 1; i < n; i++){ int temp = hold; hold = max(hold,sell - prices[i]); sell = max(sell,temp + prices[i]); } return sell; } };

121. 买卖股票的最佳时机(能够买卖一次)

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

如果你最多只允许完成一笔交易(即买入和卖出一支股票),设计一个算法来计算你所能获取的最大利润。

注意你不能在买入股票前卖出股票。

比之前的多了一种状态:

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int n = prices.size();
        if(n == 0) return 0;
        int dp[n][2][2];//多了一个状态,剩余买卖的次数
        memset(dp,0xbf,sizeof(dp));
        //初始化第1天买入和卖出;
        dp[0][0][0] = -prices[0];
        dp[0][1][1] = 0;
        for(int i = 1; i < n; i++){
            // 买入并且还剩一次是不可能的
            dp[i][0][0] = max(dp[i-1][1][1]-prices[i],dp[i-1][0][0]);
            dp[i][1][0] = max(dp[i-1][0][0]+prices[i],dp[i-1][1][0]);
            dp[i][1][1] = dp[i-1][1][1];
        }
        return max(dp[n-1][1][0],0);
    }
};

滚动数组优化:

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

123. 买卖股票的最佳时机 III

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

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

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

直接滚动数组优化版本:dp[0][ j ]表示买入状态下还剩 j 次;dp[1][j]表示卖出状态下还剩 j 次;

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int n = prices.size();
        if(n == 0) return 0;
        vector<vector<int>> dp(2,vector<int>(3,0xbfbfbfbf));
        vector<vector<int>> temp(2,vector<int>(3,0xbfbfbfbf));
        dp[0][1] = -prices[0];
        dp[1][2] = 0;
        for(int i = 1; i < n; i++){
            temp[0][0] = max(dp[0][0],dp[1][1]-prices[i]);
            temp[0][1] = max(dp[0][1],dp[1][2]-prices[i]);
            //temp[0][2]不可能;
            temp[1][0] = max(dp[1][0],dp[0][0]+prices[i]);
            temp[1][1] = max(dp[1][1],dp[0][1]+prices[i]);
            temp[1][2] = dp[1][2];
            dp = temp;
        }
        return max(dp[1][2],max(dp[1][1],dp[1][0]));
    }
};

188. 买卖股票的最佳时机 IV(基本模板)

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

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

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

class Solution {
public:
    int maxProfit(int k, vector<int>& prices) {
        //k的大小要分类讨论:
        int n = prices.size();
        if(n == 0 || k == 0) return 0;
        if(k > n/2){// k > n/2时,相当于可以交易无数次;
            int sell,hold,temp;
            sell = 0;
            hold = -prices[0];
            for(int i = 1; i < n; i++){
                temp = hold;
                hold = max(hold,sell-prices[i]);
                sell = max(sell,temp+prices[i]);
            }
            return sell;
        }
        vector<vector<int>> dp(2,vector<int>(k+1,0xbfbfbfbf));
        vector<vector<int>> temp(2,vector<int>(k+1,0xbfbfbfbf));
        dp[0][k-1] = -prices[0];
        dp[1][k] = 0;
        for(int i = 1; i < n; i++){
            for(int j = 0; j < k; j++)
                temp[0][j] = max(dp[0][j],dp[1][j+1]-prices[i]);
            for(int j = 0; j < k;j++)
                temp[1][j] = max(dp[1][j],dp[0][j]+prices[i]);
            temp[1][k] = 0;
            dp = temp;
        }
        return *max_element(dp[1].begin(),dp[1].end());
    }
};

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

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

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

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

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int n = prices.size();
        if(n == 0) return 0;
        // 比最简单的多了一种状态,冷冻状态;
        //dp[0]代表买入,dp[1]代表卖出,dp[2]代表冷冻
        vector<int> dp(3),temp(3);
        dp[0] = -prices[0];
        dp[1] = dp[2] = 0;
        for(int i = 1; i < n; i++){
            temp[0] = max(dp[0],dp[2]-prices[i]);
            temp[1] = max(dp[1],dp[0]+prices[i]);
            temp[2] = dp[1];
            dp = temp;
        }
        return max(dp[1],dp[2]);
    }
};

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

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

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

返回获得利润的最大值。

就在最简单的基础上,状态转移方程变一下就好了;

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

猜你喜欢

转载自www.cnblogs.com/Aliencxl/p/12292080.html