121. Best Time to Buy and Sell S
2017-04-08 本文已影响72人
DrunkPian0
09/04/2017
这题用局部最优解和全局最优解的标准套路来想吧,这就是dp啊。递推公式:
local[i+1]=max(local[i]+prices[i+1]-price[i],0), global[i+1]=max(local[i+1],global[i])
理解起来比较清晰:
public int maxProfit(int[] prices) {
if (prices.length < 2) return 0;
//当天卖出的最大profit
int local = 0;
int global = 0;
for (int i = 1; i < prices.length; i++) {
//今天必须要交易,可以是买或卖。
//对于1,2,3,0,2这样的,第三天赚卖了两块,第四天卖了比第三天要亏三块,
//总共profit就是2-3=-1,那就不如之前什么都没发生,从今天的价格开始买,local = 0。但是虽然重新开始了,之前的最大利润被保存起来了,从0开始再比。
local = Math.max(local + prices[i] - prices[i - 1], 0);
global = Math.max(global, local);
}
return global;
}
一道题(即便是简单题),如果不按照应有的套路来思考的话,你会在写出一些野路子的code之后commit时发现漏掉了很多test cases。之前做过一个关于括号的题目就是这样。今天这道题也是如此。
我一开始写的是一个O(n*n)的双重for循环搜索的方法,看似是没什么问题的,但是提交的时候TLE了,就不谈了。
//TLE:BRUTE FORCE
// public int maxProfit(int[] prices) {
// int res = 0;
// for (int i = 1; i < prices.length; i++)
// for (int j = 0; j < i; j++) {
// res = prices[i] - prices[j] > res ? prices[i] - prices[j] : res;
// }
// return res ;
// }
然后我其实感觉这题不需要用DP,只要维护两个变量,一个是当前最大收益,一个是最大收益的那一天的price,然后如果当天的price比取得最大收益那天的price还要高,就更新这两个值就行了;但是这么做没有办法重新选择一个新的买入价格,一旦获取了一个买入和卖出的价格就永远以这次为基准了,漏掉了一种test case , 下面这种,最大收益的那天的price永远停留在2:
[2,1,2,1,0,1,2]
正确做法:不过这个没有用DP..
public int maxProfit(int[] prices) {
if (prices.length < 2) return 0;
if (prices.length == 2) return prices[1] - prices[0] > 0 ? prices[1] - prices[0] : 0;
//当前最低价
int minPrice = prices[0];
//当前最大收益
int maxProfit = 0;
for (int i = 1; i < prices.length; i++) {
if (prices[i] < minPrice) minPrice = prices[i];
maxProfit = Math.max(prices[i] - minPrice, maxProfit);
}
return maxProfit;
}