16.买卖股票的最佳时期含手续费(medium)

1.题目链接:

714. 买卖股票的最佳时机含手续费 - 力扣(LeetCode)714. 买卖股票的最佳时机含手续费 - 给定一个整数数组 prices,其中 prices[i]表示第 i 天的股票价格 ;整数 fee 代表了交易股票的手续费用。你可以无限次地完成交易,但是你每笔交易都需要付手续费。如果你已经购买了一个股票,在卖出它之前你就不能再继续购买股票了。返回获得利润的最大值。注意:这里的一笔交易指买入持有并卖出股票的整个过程,每笔交易你只需要为支付一次手续费。 示例 1:输入: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示例 2:输入:prices = [1,3,7,5,10,3], fee = 3输出:6 提示: * 1 <= prices.length <= 5 * 104 * 1 <= prices[i] < 5 * 104 * 0 <= fee < 5 * 104https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-with-transaction-fee/description/2.题目描述:

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

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

返回获得利润的最大值。

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

示例 1:​
输入: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​
     示例 2:​
               输入:prices = [1,3,7,5,10,3], fee = 3​
               输出:6​
3. 解法(动态规划):
算法思路:
1. 状态表示:
        对于线性 dp ,我们可以用「经验 + 题目要求」来定义状态表示:​

i.

以某个位置为结尾,巴拉巴拉;

ii. 以某个位置为起点,巴拉巴拉。

这里我们选择比较常用的方式,以某个位置为结尾,结合题目要求,定义一个状态表示:由于有「买入」「可交易」两个状态,因此我们可以选择用两个数组,其中:

f[i]  表示:第 i  天结束后,处于「买入」状态,此时的最大利润;​g[i]  表示:第 i  天结束后,处于「卖出」状态,此时的最大利润。​

2. 状态转移方程:
我们选择在「卖出」的时候,支付这个手续费,那么在「买入」的时候,就不用再考虑手续费的问题。

对于 f[i] ,我们有两种情况能到达这个状态:​

i.

i - 1  天「持有」股票,第 i  天啥也不干。此时最大收益为 f[i - 1] ;​

ii.i - 1  天的时候「没有」股票,在第 i  天买入股票。此时最大收益为 g[i - 1]                  - prices[i])
两种情况下应该取最大值,因此 f[i] = max(f[i - 1], g[i - 1] -
prices[i])

对于 g[i] ,我们也有两种情况能够到达这个状态:​

i.

i - 1  天「持有」股票,但是在第 i  天将股票卖出。此时最大收益为:f[i - 1]

+ prices[i] - fee) ,记得手续费;

ii.i - 1  天「没有」股票,然后第 i  天啥也不干。此时最大收益为:g[i - 1] ;​

两种情况下应该取最大值,因此 g[i] = max(g[i - 1], f[i - 1] + prices[i]

- fee)

3. 初始化:

由于需要用到前面的状态,因此需要初始化第一个位置。

对于 f[0] ,此时处于「买入」状态,因此 f[0] = -prices[0] ;​
对于 g[0] ,此时处于「没有股票」状态,啥也不干即可获得最大收益,因此 g[0] = 0 。​

4. 填表顺序:

毫无疑问是「从左往右」,但是两个表需要一起填。

5. 返回值:

应该返回「卖出」状态下,最后一天的最大值收益:g[n - 1]

Java算法代码:

class Solution {
    public int maxProfit(int[] prices, int fee) {
        // 1.创建dp表
        // 2.初始化
        // 3.填表
        // 4.返回值
        int n = prices.length;
        int[] f = new int[n];
        int[] g = new int[n];
        f[0] = - prices[0];
        for(int i = 1; i < n; i++) {
            f[i] = Math.max(f[i - 1],g[i - 1] - prices[i]);
            g[i] = Math.max(g[i - 1],f[i - 1] + prices[i] - fee);

        }
        return g[n - 1];
    }
}

运行结果:

贪心策略:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值