Best Time to Buy and Sell Stock I II III IV
2015-09-20 11:20
357 查看
Best Time to Buy and Sell Stock I
Description: Say you have an array for which the ith element is the price of a given stock on day i. If you were only permitted to complete at most one transaction (ie, buy one and sell one share of the stock), design an algorithm to findthe maximum profit.
题意:用一个数组表示股票每天的价格,数组的第i个数表示股票在第i天的价格。 如果只允许进行一次交易,也就是说只允许买一支股票并卖掉,求最大的收益。
分析:动态规划法。从前向后遍历数组,记录当前出现过的最低价格,作为买入价格,并计算以当天价格出售的收益,作为可能的最大收益,整个遍历过程中,出现过的最大收益就是所求。
代码:O(n)时间,O(1)空间。
public class Solution { public int maxProfit(int[] prices) { if (prices.length < 2) return 0; int maxProfit = 0; int curMin = prices[0]; for (int i = 1; i < prices.length; i++) { curMin = Math.min(curMin, prices[i]); maxProfit = Math.max(maxProfit, prices[i] - curMin); } return maxProfit; } }
Best Time to Buy and Sell Stock II
Description: Say you have an array for which the ith element is the price of a given stock on day i. Design an algorithm to find the maximum profit. You may complete as many transactions as you like (ie, buy one and sell one share of thestock multiple times). However, you may not engage in multiple transactions at the same time (ie, you must sell the stock before you buy again).
题目:用一个数组表示股票每天的价格,数组的第i个数表示股票在第i天的价格。交易次数不限,但一次只能交易一支股票,也就是说手上最多只能持有一支股票,求最大收益。
分析:贪心法。从前向后遍历数组,只要当天的价格高于前一天的价格,就算入收益。
代码:时间O(n),空间O(1)。
public class Solution { public int maxProfit(int[] prices) { if (prices.length < 2) return 0; int maxProfit = 0; for (int i = 1; i < prices.length; i++) { int diff = prices[i] - prices[i - 1]; if (diff > 0) { maxProfit += diff; } } return maxProfit; } }
Best Time to Buy and Sell Stock III
Description: Say you have an array for which the ith element is the price of a given stock on day i. Design an algorithm to find the maximum profit. You may complete at most two transactions. Note: You may not engage in multiple transactionsat the same time (ie, you must sell the stock before you buy again).
题意:用一个数组表示股票每天的价格,数组的第i个数表示股票在第i天的价格。最多交易两次,手上最多只能持有一支股票,求最大收益。
分析:动态规划法。以第i天为分界线,计算第i天之前进行一次交易的最大收益preProfit[i],和第i天之后进行一次交易的最大收益postProfit[i],最后遍历一遍,max{preProfit[i] + postProfit[i]} (0≤i≤n-1)就是最大收益。第i天之前和第i天之后进行一次的最大收益求法同Best Time to Buy and Sell Stock I。
代码:时间O(n),空间O(n)。
public class Solution { public int maxProfit(int[] prices) { if (prices.length < 2) return 0; int n = prices.length; int[] preProfit = new int ; int[] postProfit = new int ; int curMin = prices[0]; for (int i = 1; i < n; i++) { curMin = Math.min(curMin, prices[i]); preProfit[i] = Math.max(preProfit[i - 1], prices[i] - curMin); } int curMax = prices[n - 1]; for (int i = n - 2; i >= 0; i--) { curMax = Math.max(curMax, prices[i]); postProfit[i] = Math.max(postProfit[i + 1], curMax - prices[i]); } int maxProfit = 0; for (int i = 0; i < n; i++) { maxProfit = Math.max(maxProfit, preProfit[i] + postProfit[i]); } return maxProfit; } }
Best Time to Buy and Sell Stock IV
Description: Say you have an array for which the ith element is the price of a given stock on day i. Design an algorithm to find the maximum profit. You may complete at most k transactions. Note: You may not engage in multiple transactionsat the same time (ie, you must sell the stock before you buy again).
题意:用一个数组表示股票每天的价格,数组的第i个数表示股票在第i天的价格。最多交易k次,手上最多只能持有一支股票,求最大收益。
分析:特殊动态规划法。传统的动态规划我们会这样想,到第i天时进行j次交易的最大收益,要么等于到第i-1天时进行j次交易的最大收益(第i天价格低于第i-1天的价格),要么等于到第i-1天时进行j-1次交易,然后第i天进行一次交易(第i天价格高于第i-1天价格时)。于是得到动规方程如下(其中diff = prices[i] – prices[i – 1]):
profit[i][j] = max(profit[i – 1][j], profit[i – 1][j – 1] + diff)
看起来很有道理,但其实不对,为什么不对呢?因为diff是第i天和第i-1天的差额收益,如果第i-1天当天本身也有交易呢,那么这两次交易就可以合为一次交易,这样profit[i – 1][j – 1] + diff实际上只进行了j-1次交易,而不是最多可以的j次,这样得到的最大收益就小了。
那么怎样计算第i天进行交易的情况的最大收益,才会避免少计算一次交易呢?我们用一个局部最优解和全局最有解表示到第i天进行j次的收益,这就是该动态规划的特殊之处。
用local[i][j]表示到达第i天时,最多进行j次交易的局部最优解;用global[i][j]表示到达第i天时,最多进行j次的全局最优解。它们二者的关系如下(其中diff = prices[i] – prices[i – 1]):
local[i][j] = max(global[i – 1][j – 1] + max(diff, 0), local[i – 1][j] + diff)
global[i][j] = max(global[i – 1][j], local[i][j])
其中的local[i – 1][j] + diff就是为了避免第i天交易和第i-1天交易合并成一次交易而少一次交易收益。 参考:http://www.cnblogs.com/grandyang/p/4295761.html
代码:时间O(n),空间O(k)。
public class Solution { public int maxProfit(int k, int[] prices) { if (prices.length < 2) return 0; if (k >= prices.length) return maxProfit2(prices); int[] local = new int[k + 1]; int[] global = new int[k + 1]; for (int i = 1; i < prices.length ; i++) { int diff = prices[i] - prices[i - 1]; for (int j = k; j > 0; j--) { local[j] = Math.max(global[j - 1] + Math.max(diff, 0), local[j] + diff); global[j] = Math.max(global[j], local[j]); } } return global[k]; } public int maxProfit2(int[] prices) { int maxProfit = 0; for (int i = 1; i < prices.length; i++) { if (prices[i] > prices[i - 1]) { maxProfit += prices[i] - prices[i - 1]; } } return maxProfit; } }
补充:这道题还有一个陷阱,就是当k大于天数时,其实就退化成 Best Time to Buy and Sell Stock II 了。就不能用动规来做了,为什么?(请思考) 另外,Best Time to Buy and Sell Stock III 就是本题k=2的情况,所以说IV是II和III的综合。
相关文章推荐
- django 1.8 官方文档翻译:13-1-3 密码管理
- jni中文字符串乱码的处理方法
- Scala教程(二)基础语法
- 2015年9月20日
- 创业的第四十四天
- 欢迎使用CSDN-markdown编辑器
- 大数据面试可能遇到的问题
- 快速矩阵幂模板
- c标签的使用方法
- Gradle多渠道打包[umeng]
- 练习一_使用Git进行代码管理的心得
- 卢梭《社会契约论》之论原始社会
- poj-1611-The Suspects(并查集)
- 变量在内存中的存储原则
- R通过 ODBC方式连接sql server
- 腾讯面试题的一些解答
- Vijos 1002 过河
- opensuse下配置IP、DNS、GATEWAY
- poj-1611-The Suspects(并查集)
- navicat for mysql导入关联的表