• 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;
        }
    };
  • 相关阅读:
    C语言数组和字符串函数
    C语言控制语句
    C语言输入输出函数
    C语言运算符
    C语言数据类型
    嵌入式开发基础知识
    VI编辑器的使用
    Linux文件系统和目录相关命令
    前段之必学(转载)
    26个高效工作的小技巧(转载)
  • 原文地址:https://www.cnblogs.com/Aliencxl/p/12292080.html
Copyright © 2020-2023  润新知