题号 121
题目描述
给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。
如果你最多只允许完成一笔交易(即买入和卖出一支股票一次),设计一个算法来计算你所能获取的最大利润。
注意:你不能在买入股票前卖出股票。
示例1:
输入: [7,1,5,3,6,4]
输出: 5
解释: 在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。
注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格;同时,你不能在买入前卖出股票。
示例2:
输入: [7,6,4,3,1]
输出: 0
解释: 在这种情况下, 没有交易完成, 所以最大利润为 0。
解题思路一——暴力法(超出时间限制)
数组的第 i 个元素表示该顾飘第 i 天的价格,假设我们在第 i 天买入该股票,分别计算第 i +1 天~第 n 天卖出可获得利润,取其中最大的利润记为 ans。
令 i 依次为 0 ~ n,重复上述过程,最后 ans 就是我们需要的结果。
代码如下:
class Solution {
public:
int maxProfit(vector<int>& prices) {
int n = prices.size(), ans = 0;
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
ans = max(ans, prices[j] - prices[i]);
}
}
return ans;
}
};
时间复杂度:O(n^2)
空间复杂度:O(1)
解题思路二(超出时间限制)
使用数组 p 来记录每一天卖出可获得的最大利润值,比如 p[ i ] 表示第 i 天卖出股票时,可获得的最大利润值。
在计算 p[ i ] 时,取给定数组的前 i 个元素中的最小值,如果最小值大于第 i 个元素的值,则 p[ i ] = 0;否则 p [ i ] = 第 i 个元素的值 - 最小值。
最后取数组 p 中的最大值即可。
代码如下:
class Solution {
public:
int maxProfit(vector<int>& prices) {
int n = prices.size();
vector<int> p(n);
if (n == 0)
return 0;
if (n == 1)
return 0;
p[0] = 0;
for (int i = 1; i < n; i++) {
int minPrice = *min_element(prices.begin(), prices.begin() + i);
if (minPrice > prices[i])
p[i] = 0;
else
p[i] = prices[i] - minPrice;
}
return *max_element(p.begin(), p.end());
}
};
时间复杂度:O(n^2)
空间复杂度:O(n)
解题思路三——动态规划解题
Step1、2:描述问题的最优解结构特征,递归定义最优解值
设 p[ i ] 表示第 i 天卖出股票时所能获取的最大利润,题目中给定的数组命名为 prices,显然 p[ i ] = prices[ i ] - 前 i -1个元素中的最小值。
假设前 i - 1 个元素的最小值为 minVal,显然有 p[ i - 1 ] = prices[ i - 1 ] - minVal
则:minVal = prices[ i - 1] - p[ i - 1 ]
所以 p[ i ] = max { p[ i - 1] + prices[ i ] - prices[ i - 1 ] , 0 }
Step3、4:自底向上计算最优解值、输出最优解值
问题的底为:p[ 0 ] = 0
为了节省空间,我们可以不使用数组来存储每天卖出顾飘所能获取的最大利润,而是使用两个变量 F_i 和 F_i_1进行迭代,同时使用 maxVal 记录前 i 天中卖出股票可获取的最大利润值。【值得借鉴!!!】
循环结束后,maxVal 就是我们所要求的结果。
代码如下:
class Solution {
public:
int maxProfit(vector<int>& prices) {
if (!prices.size())
return 0;
int maxVal = 0;
int Fi_1 = 0, Fi = 0;
for (int i = 1; i < prices.size(); i++) {
Fi = max(Fi_1 + prices[i] - prices[i - 1], 0);
maxVal = max(Fi, maxVal);
Fi_1 = Fi;
}
return maxVal;
}
};
时间复杂度:O(n)
空间复杂度:O(1)