[LintCode 1691.] 买卖股票的最佳时机V

LintCode 1691. 买卖股票的最佳时机V

题目描述

给出一个股票n天的价格,每天最多只能进行一次交易,可以选择买入一支股票或卖出一支股票或放弃交易,输出能够达到的最大利润值

样例

样例 1:

给出 a = [1,2,10,9], 返回 16
输入:
[1,2,10,9]
输出:
16
解释:
你可以在第一天和第二天买入股票,第三天和第四天卖出
利润:-1-2+10+9 = 16
样例 2:

给出 a = [9,5,9,10,5], 返回 5
输入:
[9,5,9,10,5]
输出:
5
解释:
你可以在第2天买入,第4天卖出
利润:-5 + 10 = 5

注意事项

1 ≤ n ≤ 10000

解题思路

这道股票买卖问题,与以往的限制一次买卖、限制两次买卖、限制k次买卖、限制卖出后才能下一次买入……都不同,并不限制持有的股票数量,可以随时买入卖出。
这里直接使用状态转移方程,每一天有3个状态:买入、卖出、无操作。
使用dp[i][j]表示第i天持有j只股票的最大收益,则 dp[i][j] = max(dp[i-1][j-1]-a[j-1], dp[i-1][j+1]+a[j-1], dp[i-1][j])

参考代码

class Solution {
public:
    /**
     * @param a: the array a
     * @return: return the maximum profit
     */
    int getAns(vector<int> &a) {
        // write your code here
        if (a.size() <= 1) return 0;

        size_t n = a.size();
        vector<vector<int>> dp(n+1, vector<int>(n+1)); // 前 i 天进行 j 次买卖的最大利润
        for (int i=0; i<n; i++) {
            dp[i][0] = 0;
            dp[0][i] = 0;
        }
        for (int i=1; i<=n; i++) {
            dp[i][0] = std::max(dp[i-1][0], dp[i-1][1]+a[i-1]);
            dp[i][i] = dp[i-1][i-1] - a[i-1];
            dp[i][i-1] = std::max(dp[i-1][i-1], dp[i-1][i-2] - a[i-1]);
            for (int j=1; j<=i-2; j++) {
                dp[i][j] = max3(
                    dp[i-1][j],         // 不操作
                    dp[i-1][j-1]-a[i-1],// 买入
                    dp[i-1][j+1]+a[i-1] // 卖出
                    );
            }
        }
        int res = 0;
        for (int j=0; j<n; j++) {
            res = std::max(res, dp[n][j]);
        }
        return res;
    }
    static inline int max3(int a, int b, int c) {
        int m = a > b ? a : b;
        return m > c ? m : c;
    }
};

minor fix:

  • if(i>=2) dp[i][i-1] = std::max(dp[i-1][i-1], dp[i-1][i-2] - a[i-1]);
  • 不从dp[n]中选最大值,直接return dp[n][0];
原文地址:https://www.cnblogs.com/zhcpku/p/14261598.html