动态规划解决简化的股票买卖问题

1. 前言

        今天在leetcode上看到了一道dp解决股票买卖最大利润的问题,联想到了今年美赛的C题,当时对动态规划还是一知半解,也完全没有往这方面去想。故记录一下这题的思路,也是提醒自己要提高对动态规划的理解,事实上许多数模国一论文都有涉及动态规划的内容。

        动态规划的内容可以看看之前算法设计的PPT。

        或者参考下别人的博客,如动态规划详解_Ashley zhao的博客-CSDN博客_动态规划

2. 题目描述

        原题可见力扣

        

给定一个整数数组 prices,其中 prices[i]表示第 i 天的股票价格 ;整数 fee 代表了交易股票的手续费用

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

返回获得利润的最大值。

注意:这里的一笔交易指买入持有并卖出股票的整个过程,每笔交易你只需要为支付一次手续费。

        下面是一个例子:

输入:prices = [1, 3, 2, 8, 4, 9], fee = 2
输出:8
解释:能够达到的最大利润:  
在此处买入 prices[0] = 1
在此处卖出 prices[3] = 8
在此处买入 prices[4] = 4
在此处卖出 prices[5] = 9
总利润: ((8 - 1) - 2) + ((9 - 4) - 2) = 8

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-with-transaction-fee
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

3. 问题求解

        此问的解法在leetcode上都可以看到,这里我顺带着复习下动归的解题步骤。

        ①:明确优化目标,建立递归方程

        ②:给定初始条件,自底向上求解各个子问题

        ③:根据递归方程编程实现,得到优化解

3.1 建立递归方程

        为了方便讨论,我们把手续费放到抛售的时候计算。

        首先,构建二维数组 res[2][N],N为天数。

        其中 res[0][i] 代表第 i 天未持股的情况下,前 i 天的最大收益;res[1][i] 代表第 i 天持股的情况下,前 i 天的最大收益

        这样,原先求 N 天后最大利润的问题转变为求 res[0][N] 与 res[1][N]中的最大值(当然实际上就是res[0][N])。接下来,就可以建立递归方程了。

        注意到 res[0][i] 是由前一天的情况转变而来的,分为两种情况:

        若第 i-1 天未持股,则 res[0][i] = res[0][i-1];

        若第 i-1 天持股,则前 i 天收益等于前 i-1 天收益加上第 i 天买入股票的收益,即 res[0][i] = res[1][i-1] + price[i] - fee。

        由于是求最大值,所以 res[0][i] = max(res[0][i-1], res[1][i-1] - price[i])

        类似的,可以得到 res[1][i] = max(res[1][i-1], res[0][i-1] + price[i] - fee)

3.2 给定初始条件

        在第 0 天时,若未持股则收益为0,否则说明买股,收益为 -price[i]。

        即 res[0][0] = 0,res[1][0] = -price[i]。

3.3 问题求解

        这是leetcode上给出的官方代码(c++),可以参考。

int maxProfit(vector<int>& prices, int fee) {
        int n = prices.size();
        vector<vector<int>> dp(n, vector<int>(2));
        dp[0][0] = 0, dp[0][1] = -prices[0];
        for (int i = 1; i < n; ++i) {
            dp[i][0] = max(dp[i - 1][0], dp[i - 1][1] + prices[i] - fee);
            dp[i][1] = max(dp[i - 1][1], dp[i - 1][0] - prices[i]);
        }
        return dp[n - 1][0];
    }

作者:LeetCode-Solution
链接:https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-with-transaction-fee/solution/mai-mai-gu-piao-de-zui-jia-shi-ji-han-sh-rzlz/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值