LintCode 1000 · Best Time to Buy and Sell Stock with Transaction Fee (股票问题好题)

文章介绍了在考虑交易费用的情况下,如何使用动态规划解决股票买卖问题以实现最大利润。给出了三种不同的解法,包括空间优化版本,以及针对大规模数据的时间复杂度优化。

1000 · Best Time to Buy and Sell Stock with Transaction Fee
Algorithms
Medium

Description
Given an array of integers prices, for which the i-th element is the price of a given stock on day i; and a non-negative integer fee representing a transaction fee. (You need to pay fee only on selling.)

You can complete as many transactions as you like, but you need to pay the transaction fee for each transaction. You can not buy more than 1 share of a stock at a time (ie. you must sell the stock share before you buy again.)

Return the maximum profit you can make.
0 < prices.length <= 50000.
0 < prices[i] < 50000.
0 <= fee < 50000.

Example
Example 1:

Input: prices = [1, 3, 2, 8, 4, 9], fee = 2
Output: 8
Explanation: The maximum profit can be achieved by:
Buying at prices[0] = 1
Selling at prices[3] = 8
Buying at prices[4] = 4
Selling at prices[5] = 9
The total profit is ((8 - 1) - 2) + ((9 - 4) - 2) = 8.
Example 2:

Input: prices = [1, 4, 6, 2, 8, 3, 10, 14], fee = 3
Output: 13
Tags
Company
Facebook
Related Problems

150
Best Time to Buy and Sell Stock II
Medium

解法1:用DP。
dp[i][0]: the maximum profit at the i-th day if no stock is hold
dp[i][1]: the maximum profit at the i-th day if the stock is hold
注意:
dp[0][1] = INT_MIN / 2; //important!!!
不然,默认其为0的话,比较dp[0][0]和dp[0][1]+price[0]-fee的时候就可能会选dp[0][1]+price[0]-fee。但这是不对的,因为第0天不可能有股票。注意天数从1开始。

class Solution {
public:
    /**
     * @param prices: a list of integers
     * @param fee: a integer
     * @return: return a integer
     */
    int maxProfit(vector<int> &prices, int fee) {
        int n = prices.size();
        if (n == 0) return 0;
        //dp[i][0]: the maximum profit at the i-th day if no stock is hold
        //dp[i][1]: the maximum profit at the i-th day if the stock is hold
        vector<vector<int>> dp(n + 1, vector<int>(2, 0));
        dp[0][1] = INT_MIN / 2; //important!!!
        for (int i = 1; i <= n; i++) {
            dp[i][0] = max(dp[i - 1][0], dp[i - 1][1] + prices[i - 1] - fee);
            dp[i][1] = max(dp[i - 1][0] - prices[i - 1], dp[i - 1][1]);
        }
        return dp[n][0];
    }
};

空间优化:滚动数组

class Solution {
public:
    /**
     * @param prices: a list of integers
     * @param fee: a integer
     * @return: return a integer
     */
    int maxProfit(vector<int> &prices, int fee) {
        int n = prices.size();
        if (n == 0) return 0;
        //dp[i][0]: the maximum profit at the i-th day if no stock is hold
        //dp[i][1]: the maximum profit at the i-th day if the stock is hold
        vector<vector<int>> dp(2, vector<int>(2, 0));
        dp[0][1] = INT_MIN / 2; //important!!!
        for (int i = 1; i <= n; i++) {
            dp[i % 2][0] = max(dp[(i - 1) % 2][0], dp[(i - 1) % 2][1] + prices[i - 1] - fee);
            dp[i % 2][1] = max(dp[(i - 1) % 2][0] - prices[i - 1], dp[(i - 1) % 2][1]);
        }
        return dp[n % 2][0];
    }
};

另一种空间优化:用no_hold和hold变量代替就可以。

class Solution {
public:
    /**
     * @param prices: a list of integers
     * @param fee: a integer
     * @return: return a integer
     */
    int maxProfit(vector<int> &prices, int fee) {
        int n = prices.size();
        if (n == 0) return 0;
        int no_hold = 0, hold = INT_MIN / 2;
        for (int i = 1; i <= n; i++) {
            no_hold = max(no_hold, hold + prices[i - 1] - fee);
            hold = max(no_hold - prices[i - 1], hold);
        }
        return no_hold;
    }
};

解法2:我之前的解法会超时。

class Solution {
public:
    /**
     * @param prices: a list of integers
     * @param fee: a integer
     * @return: return a integer
     */
    int maxProfit(vector<int> &prices, int fee) {
        int n = prices.size();
        if (n == 0) return 0;
        if (n == 1) return -2;
        vector<int> dp(n + 1, 0);
        for (int i = 2; i <= n; i++) {
            for (int j = 1; j < i; j++) {
                if (prices[i - 1] > prices[j - 1] + fee) {
                    dp[i] = max(dp[i], dp[j - 1] + prices[i - 1] - prices[j - 1] - fee);
                }
            }
        }
        return dp[n];
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值