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 (i.e., buy one and sell one share of the stock), design an algorithm to find the maximum profit.
Note that you cannot sell a stock before you buy one.
Example 1:
Input: [7,1,5,3,6,4]
Output: 5
Explanation: Buy on day 2 (price = 1) and sell on day 5 (price = 6), profit = 6-1 = 5.
Not 7-1 = 6, as selling price needs to be larger than buying price.
Example 2:
Input: [7,6,4,3,1]
Output: 0
Explanation: In this case, no transaction is done, i.e. max profit = 0.
题意:最多可以交易一次,求买卖股票得到的最大利润是多少。
解法1 暴力
暴力求解每对下标的差值,找到最大值。结果超出时间限制。具体代码如下:
class Solution {
public:
int maxProfit(vector<int>& prices) {
int maxSum = 0;
for (int i = 0; i < prices.size(); ++i)
for (int j = i + 1; j < prices.size(); ++j)
if (prices[j] - prices[i] > maxSum)
maxSum = prices[j] - prices[i];
return maxSum;
}
};
解法2 动态规划
在上面的求解过程中,存在许多重复的子问题。如:
Input : [7,1,5,3,6,4] 下面都是差值:
maxProfit[0] = 0, p[i] = prices[i]
第一次: p[1] - p[0] = maxProfit[1]
第二次: max(p[2] - p[1], p[2] - p[0], maxProfit[1]) = maxProfit[2]
第三次: max(p[3] - p[2], p[3] - p[1], p[3] - p[0], maxProfit[2]) = maxProfit[3]
...
每次求解中,都要分别以当前的价格和前面的所有价格相减(太慢!),求出各差值,然后和之前得到的最大利润比较,从而得到当前的最大利润。
思考一下,就会发现,和前面的所有价格相减没有必要,只需要和前部分中的最小价格相减,就一定可以得到最大差值。然后和之前的最大利润比较即可。于是有了下面的代码:
class Solution {
public:
int maxProfit(vector<int>& prices) {
if (prices.empty()) return 0;
//dp[i]为前i天中最多一次交易可得的最大收益
//前i天的最大收益 = max{前i-1天的最大收益,第i天的股价-前i-1天中的最小股价}
//dp[i] = max(dp[i - 1], prices[i] - minPrice)
int mx = 0, mi = prices[0]; //dp[0]=0, 最小的股价=prices[0]
for (int i = 1; i < prices.size(); ++i) {
mx = max(mx, prices[i] - mi); //dp[i]
mi = min(mi, prices[i]);
}
return mx;
}
};
对应的Java版本如下:
class Solution {
public int maxProfit(int[] prices) {
if (prices == null || prices.length <= 1) return 0;
int maxprofit = 0, minprice = prices[0];
//dp[i]是第i天得到的最高利润,只能交易一次,因此此时的最高利润为max(maxProfit, 此时的价格-之前的最低价格)
for (int i = 1; i < prices.length; ++i) {
maxprofit = Math.max(maxprofit, prices[i] - minprice);
minprice = Math.min(minprice, prices[i]);
}
return maxprofit;
}
}