Leetcode-Algorithm-DP-121
-
题目:
-
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 find the maximum profit.
(假定你有一个数组,数组中的每个元素表示元素所在索引的那天的价格。如果你只被允许最多完成一次交易,也就是进行一次买卖,请设计一个算法找到最大的收益。)
例子:
输入:[7, 1, 5, 3, 6, 4].
输出:5.
解释:由于只能进行一次交易,因此在第一天买入和在第4天卖出能得到的收益最大,收益为6-1=5。
输入:[7, 6, 4, 3, 1].
输出:0.
解释:由于卖出日期必须大于买入日期,因此对于当前数组无论怎么样的买卖都不能得到正的收益,因此,最大收益为0。
题解:
方法1:(暴力法)
做容易想的办法就是把所有可能的买卖收益计算出来,然后找出其中的最大值。所谓“可能的买卖”也就是在卖出日期大于等于买入日期的前提下进行所有的一次买卖。
class Solution {
public:
int maxProfit(vector<int>& prices) {
int max = 0;
for (int i = 0; i < prices.size(); ++i)
for (int j = i+1; j < prices.size(); ++j)
max = (max > (prices[j]-prices[i]) ? max : prices[j]-prices[i]);
return max;
}
};
分析:
由于要计算出所有索引i和j间且i<=j的差值,因此总的时间复杂度为
O(n2)
。在leetcode上会导致超时。
方法2:(动态规划DP)
虽然不清楚怎么样的买卖组合才能得到最大的收益,但是我们知道,在允许买卖的那天开始(也就是索引为0,第0天)到之后的某一天(第i天),期间的最大收益有两种可能:①到第i天的最大收益就是到第i-1天的收益,也就是说第i天的价格不影响前i-1天的最大收益;②当第i天的价格会影响前i-1天的最大收益时,也就是说在第i天卖出能够得到更大的收益,这时最大收益就是第i天的价格减去前i-1天的最低价格。所以可以通过动态规划解决这个问题。状态转移函数为:f(i)=max{f(i-1), prices[i]-minPrice},其中f(i)表示到第i天为止得到的最大收益,minPrice表示钱i-1天的最低价格。
class Solution {
public:
int maxProfit(vector<int>& prices) {
if (prices.empty()) return 0;
vector<int> profit;
int maxPro = 0;
int minPrice = prices[0];
profit.push_back(0);
for (int i = 1; i < prices.size(); ++i) {
minPrice = min(prices[i], minPrice);
profit.push_back(max(profit[i-1], prices[i] - minPrice));
maxPro = max(maxPro, profit[i]);
}
return maxPro;
}
};
分析:
由于算法的整个过程只需要遍历一次prices容器,因此总的时间复杂度为
O(n)
。