LeetCode 动态规划之买卖股票的最佳时机含手续费

简介: LeetCode 动态规划之买卖股票的最佳时机含手续费

题目


给定一个整数数组 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 * 104


题解


解题分析


题目描述: 给定每日股票价格的数组,每天可以选择是否买入/卖出,持有时不能再次买入,每笔交易有固定的手续费,求可获得的最大利润。


解题思路:


  1. 我们可以从题目可以看到,本题是一个典型的动态规划问题。


  1. 对于动态规划问题我们可以总结一下思路:


  • 定义状态转移方程
  • 给定转移方程初始值
  • 通过代码递推首先转移方程


  1. 结合本题目我们首先定义转移方程


定义一个二维数组 dp[n][2]:


  • dp[i][1] 表示第 i 天不持有可以获得的最大利润;


  • dp[i][2] 表示第 i 天持有获得的最大利润(注意是第 i 天持有,而不是第 i 天买入)。


定义转移方程:


  • 不持有: dp[i][0] = max(dp[i-1][0], dp[i-1][1] + price[i] - fee)


对于今天不持有,可以从两个状态转移过来,1. 昨天也不持有;2. 昨天持有,今天卖出。获取最大值


  • 持有:  dp[i][1] = max(dp[i-1][1], dp[i-1][0] - price[i])


对于今天持有, 可以从两个状态转移过来,1. 昨天也持有;昨天不持有,今天买入,获取最大值


  1. 给转移方程初始化值


对于第 0 天: - 不持有: dp[0][0] = 0; - 持有(即花钱买入):dp[0][1] = -prices[0];


  1. 代码实现转移方程


class Solution {
    public int maxProfit(int[] prices, int fee) {
        int n = prices.length;
        int[][] dp = new int[n][2];
        dp[0][0] = 0;
        dp[0][1] = -prices[0];
        for (int i=0; i< n; i++) {
           dp[i][0] = Math.max(dp[i-1][0], dp[i -1][1] + prices[i] - fee);
           dp[i][1] = Math.max(dp[i-1][1], dp[i-1][0] - prices[i]);
        }
        return dp[n-1][0];
    }
}


由于我们只需要用到前一次的数据,可以进行空间优化,在转移的时候 dp[i] 从 dp[i-1] 转移而来, 因此可以去掉一维数组。最终解题代码所示。


复杂度分析


  • 时间复杂度:O(N)


  • 空间复杂度:O(1), 我们没有创建额外的数组来存储。


解题代码


题解代码如下(代码中有详细的注释说明):


class Solution {
    public int maxProfit(int[] prices, int fee) {
        int n = prices.length;
        // sell 表示卖出的最大收益
        int sell = 0, buy = -prices[0];
        for (int i = 1; i < n; i++) {
            sell = Math.max(sell, buy + prices[i] - fee);
            buy = Math.max(buy, sell - prices[i]);
        }
        return sell;
    }
}


提交后反馈结果:


image.png


参考信息




相关文章
|
3月前
|
算法 Python
【Leetcode刷题Python】309. 最佳买卖股票时机含冷冻期
解决LeetCode上309题“最佳买卖股票时机含冷冻期”的Python代码示例,利用动态规划方法计算在含有冷冻期约束下的最大利润。
40 1
|
3月前
|
算法 Python
【Leetcode刷题Python】121. 买卖股票的最佳时机
解决LeetCode上121题“买卖股票的最佳时机”的Python代码示例,采用一次遍历的方式寻找最佳买卖时机以获得最大利润。
59 1
|
3月前
|
算法
leetcode188 买卖股票的最佳时机IV
leetcode188 买卖股票的最佳时机IV
61 0
|
3月前
|
算法 Python
【Leetcode刷题Python】714. 买卖股票的最佳时机含手续费
提供了两种解决买卖股票最佳时机含手续费问题的Python实现方法:贪心算法和动态规划算法。
41 0
|
3月前
|
算法 Python
【Leetcode刷题Python】122.买卖股票的最佳时机 II
LeetCode "买卖股票的最佳时机 II" 问题的Python代码实现,采用贪心算法在股票价格上升的每一天买入并卖出,以获得最大利润。
21 0
|
5月前
|
算法 索引
力扣每日一题 6/28 动态规划/数组
力扣每日一题 6/28 动态规划/数组
51 0
|
5月前
|
存储
力扣每日一题 6/19 排序+动态规划
力扣每日一题 6/19 排序+动态规划
30 0
|
2月前
|
Unix Shell Linux
LeetCode刷题 Shell编程四则 | 194. 转置文件 192. 统计词频 193. 有效电话号码 195. 第十行
本文提供了几个Linux shell脚本编程问题的解决方案,包括转置文件内容、统计词频、验证有效电话号码和提取文件的第十行,每个问题都给出了至少一种实现方法。
LeetCode刷题 Shell编程四则 | 194. 转置文件 192. 统计词频 193. 有效电话号码 195. 第十行
|
3月前
|
Python
【Leetcode刷题Python】剑指 Offer 32 - III. 从上到下打印二叉树 III
本文介绍了两种Python实现方法,用于按照之字形顺序打印二叉树的层次遍历结果,实现了在奇数层正序、偶数层反序打印节点的功能。
54 6
|
3月前
|
搜索推荐 索引 Python
【Leetcode刷题Python】牛客. 数组中未出现的最小正整数
本文介绍了牛客网题目"数组中未出现的最小正整数"的解法,提供了一种满足O(n)时间复杂度和O(1)空间复杂度要求的原地排序算法,并给出了Python实现代码。
107 2