09/04/2017
這題用局部最優(yōu)解和全局最優(yōu)解的標準套路來想吧,這就是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,那就不如之前什么都沒發(fā)生,從今天的價格開始買,local = 0。但是雖然重新開始了,之前的最大利潤被保存起來了,從0開始再比。
local = Math.max(local + prices[i] - prices[i - 1], 0);
global = Math.max(global, local);
}
return global;
}
一道題(即便是簡單題),如果不按照應(yīng)有的套路來思考的話,你會在寫出一些野路子的code之后commit時發(fā)現(xiàn)漏掉了很多test cases。之前做過一個關(guān)于括號的題目就是這樣。今天這道題也是如此。
我一開始寫的是一個O(n*n)的雙重for循環(huán)搜索的方法,看似是沒什么問題的,但是提交的時候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;
}