Best Time to Buy and Sell Stock with Transaction Fee

题目等级:Medium

题目描述:

Your are 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 may complete as many transactions as you like, but you need to pay the transaction fee for each transaction. You may 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.

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.

  题意:给定一个整数数组 prices,其中第 i 个元素代表了第 i 天的股票价格 ;非负整数 fee 代表了交易股票的手续费用。可以无限次地完成交易,但是每次交易都需要付手续费。返回获得利润的最大值。


解题思路(动态规划):

  终于到了买卖股票的最后一道题。。。

  有了上一题(冷冻期)的经验,这道题实际不难了,同样是无数次情况的一个变形,只不过每次需要交一定的费用。实际很类似,有了上一题状态的定义,稍加修改就是这个题了。

  同样的,每一天是一个阶段,每一阶段的决策就是:每天决定买还是卖,而每一天有两个状态:手里持有股票、手里没有股票

  和上题一样,仍然定义两个状态变量:

  sell[i]:表示在第i天结束后手里没有股票的情况下,获得的最大收益。

  hold[i]:表示在第i天结束后手里仍然持有股票的情况下获得的最大收益。

  其状态转移也不难分析:

  如果当天结束时仍然持有股票,那么有两种可能:(1)今天刚买的,那么说明前一天结束的时候手里没有股票了,即hold[i]=sell[i-1]-prices[i]. (2)以前就买了,今天啥也没干,也没买也没卖,换句话说就是前一天结束的时候手里已经有了,即:hold[i]=hold[i-1]

  如果当天结束的时候手里没有股票,那么说明也有两种可能:(1)今天刚卖了, 也就是说前一天结束的时候手里还是持有股票的,而今天卖的时候还有交纳费用,所以:sell[i]=hold[i-1]+prices[i]-fee.(2)以前就卖了,今天啥也没干,那说明前一天结束的时候手里已经没有股票了,所以:sell[i]=sell[i-1].

  综合起来,就可以得到状态转移方程:

	hold[i]=max(sell[i-1]-prices[i],hold[i-1])
sell[i]=max(hold[i-1]+prices[i]-fee,sell[i-1])

  初始条件还是一样的,第一天的时候不可能卖出,一定会买入,这实际上还是贪心思想的一种体现,第一天可以买一定是会买的,在处理不限次数的交易时,已经证明了这种贪心思想的正确性,所以sell[0]=0,而hold[0]=-prices[0].

  最后,根据以上分析给出以下代码:

    public int maxProfit(int[] prices, int fee) {
if(prices==null || prices.length==0)
return 0;
int len=prices.length;
int[] sell=new int[len];
int[] hold=new int[len];
sell[0]=0;
hold[0]=-prices[0];
for(int i=1;i<len;i++){
sell[i]=Math.max(sell[i-1],hold[i-1]+prices[i]-fee);
hold[i]=Math.max(sell[i-1]-prices[i],hold[i-1]);
}
return sell[len-1];
}
}

  时间复杂度:O(n),空间复杂度:O(2n)

总结

  本题是买卖股票6道题的最后一题了,做一个简单的总结,这一系列题目是动态规划和贪心思想的运用。我们可以看到:实际上在冷冻期和需要费用的这两道题目中定义的两个状态sell和hold是可以解决所有的不限制交易次数的题目的,包括我们的无数次交易也可以通过这两个状态来写出转移方程,因为不管条件如何变,只要没有限制交易次数,每天的状态都还是这两个。而限制了交易次数的,状态就会复杂一些,就需要一个二维状态,这也就是在允许交易K次的题目中我们给出的方法。

  因此,到此为止,不管股票买卖这道题再给出什么条件,我们都可以做了,因为限制次数的和不限制次数的两种情况下的状态我们都清楚了,只需要根据不同的条件写出转移方程就可以了。

  一次交易:【LeetCode】121、买卖股票的最佳时机

  两次交易:【LeetCode】123、买卖股票的最佳时机 III

  K次交易:【LeetCode】188、买卖股票的最佳时机 IV

  无数次交易:【LeetCode】122、买卖股票的最佳时机 II

  无数次交易含冷冻期:【LeetCode】309、最佳买卖股票时机含冷冻期

  无数次交易含交易费用:【LeetCode】714、买卖股票的最佳时机含手续费

【LeetCode】714、买卖股票的最佳时机含手续费的更多相关文章

  1. Java实现 LeetCode 714 买卖股票的最佳时机含手续费(动态规划 || 迭代法)

    714. 买卖股票的最佳时机含手续费 给定一个整数数组 prices,其中第 i 个元素代表了第 i 天的股票价格 :非负整数 fee 代表了交易股票的手续费用. 你可以无限次地完成交易,但是你每次交 ...

  2. LeetCode——714. 买卖股票的最佳时机含手续费.

    给定一个整数数组 prices,其中第 i 个元素代表了第 i 天的股票价格 :非负整数 fee 代表了交易股票的手续费用. 你可以无限次地完成交易,但是你每次交易都需要付手续费.如果你已经购买了一个 ...

  3. leetcode 714. 买卖股票的最佳时机含手续费

    继承leetcode123以及leetcode309的思路,,但应该也可以写成leetcode 152. 乘积最大子序列的形式 class Solution { public: int maxProf ...

  4. Leetcode之动态规划(DP)专题-714. 买卖股票的最佳时机含手续费(Best Time to Buy and Sell Stock with Transaction Fee)

    Leetcode之动态规划(DP)专题-714. 买卖股票的最佳时机含手续费(Best Time to Buy and Sell Stock with Transaction Fee) 股票问题: 1 ...

  5. [Swift]LeetCode714. 买卖股票的最佳时机含手续费 | Best Time to Buy and Sell Stock with Transaction Fee

    Your are given an array of integers prices, for which the i-th element is the price of a given stock ...

  6. 每日一题-——LeetCode(121)买卖股票的最佳时机

    题目描述: 给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格.如果你最多只允许完成一笔交易(即买入和卖出一支股票),设计一个算法来计算你所能获取的最大利润.注意你不能在买入股票前卖出股票 ...

  7. Leetcode 188.买卖股票的最佳时机IV

    买卖股票的最佳时机IV 给定一个数组,它的第 i 个元素是一支给定的股票在第 i 天的价格. 设计一个算法来计算你所能获取的最大利润.你最多可以完成 k 笔交易. 注意: 你不能同时参与多笔交易(你必 ...

  8. LeetCode《买卖股票的最佳时机》系列题目,最详解

    目录 说在前面 引例:只能交易一次 一.动态数组定义 二.状态转移方程 三.初始化 四.优化 无限制买卖 一.动态数组定义 二.状态转移方程 三.初始化 四.优化 交易 2 次,最大利润? 一.动态数 ...

  9. Leetcode——121. 买卖股票的最佳时机

    题目描述:买卖股票的最佳时机 题目要求求解能获得最大利润的方式? 可以定一个二维数组 d [ len ] [ 2 ] ,其中d[ i ][ 0 ] 表示前i天可以获得的最大利润:d[ i ][ 1 ] ...

随机推荐

  1. 树形结构根据最后一位的id匹配整个路径

    function recursionTreeId(_arr, _id) { _arr.forEach(item => { if (item.id === _id) { optionArr.uns ...

  2. shell知识点(二)

    Shell 中的数组 Shell 数组用括号来表示,元素用"空格"符号分割开,语法格式如下: 方式2: arr=(value1 value2 value3)   (这种方式带值) ...

  3. 命令方式 搭建 (简易)Maven项目

    原料:1.配好的Maven环境变量    2.c m d命令 win  + r  输入 cmd 切换到此项目所要存在的位置 使用命令创建文件夹 切换 到 maven_demo中  输入 cd mave ...

  4. C# 扩展方法——获得枚举的Description

    其他扩展方法详见:https://www.cnblogs.com/zhuanjiao/p/12060937.html /// <summary> /// 扩展方法,获得枚举的Descrip ...

  5. MySQL--关于MySQL的那些练习题

    之前联系了一些MySQL的查询相关知识,现在补充作为一个记录,免得自己忘记. 致谢博主:https://blog.csdn.net/dehu_zhou/article/details/52881587 ...

  6. 在CentOS/Windows下配置Nginx(以及踩坑)

    在CentOS/Windows下配置Nginx(以及踩坑) 1. 序言 因为这类文章网上比较多,实际操作起来也大同小异,所以我并不会着重于详细配置方面,而是将我配置时踩的坑写出来. 2. CentOS ...

  7. C/C++预处理指令#define,条件编译#ifdefine

    本文主要记录了C/C++预处理指令,常见的预处理指令如下: #空指令,无任何效果 #include包含一个源代码文件 #define定义宏 #undef取消已定义的宏 #if如果给定条件为真,则编译下 ...

  8. 轮播图和xadmin后台管理

    一.数据库设计 轮播图 1.安装依赖 pip install Pillow 2.模型类:home/models.py class Banner(models.Model): ""& ...

  9. JIRA7.13版本创建项目:工作流(二)

    工作流 在上一篇文章中,我们新建了一个问题类型,并且增加到问题类型方案里了,同时又关联到我们的这个项目中.那么这些问题我们需要如何设置流程走向来表示问题的处理过程呢?这就需要设定一个流程,并将这个流程 ...

  10. 如何在一个页面使用多个router-view显示不同的内容

    todo https://www.jianshu.com/p/92f61bf9db81