题目地址:力扣
首先这道题的第一种解法,就是暴力解,时间复杂度为O(),这种方法过于简单因此这里不展开了。
解法2:这道题的解法可以转化为我之前刷过的一道题 LeetCode 53.最大子数组和(C++)
因为要求股票收益的最大值,因此我可以新建一个数组用来存取每两天股票价格的差值,这样N天就可以构造一个大小为N-1的数组,这个数组里面存放着每两天股票涨了多少或者跌了多少。因此对这样一个数组,我们可以将求股票利益最大的原问题转化为求这个数组中最大的子数组和的问题。
代码如下:
class Solution {
public:
int maxProfit(vector<int>& prices) {
int profit = 0; // 存取全局的最大收益
vector<int> profit_arr; // 存放每两天股票的差值
if (prices.size() == 1) // 考虑只有一天的情况(边界条件)
return profit;
else { // 构建差值数组
for (auto it = prices.cbegin() + 1; it != prices.cend(); ++it)
{
profit_arr.push_back(*it - *(it - 1));
}
}
int cur_profit = 0; // 存取当前最大收益
// 针对差值数组进行求最大子数组和的操作
for (auto it = profit_arr.cbegin(); it != profit_arr.cend(); ++it)
{
if ( cur_profit + *it < 0 )
{
cur_profit = 0;
continue;
}
else {
cur_profit += *it;
if (cur_profit > profit)
profit = cur_profit;
}
}
return profit;
}
};
解法3:单次遍历
要求股票收益最大的时候,那么只需要在每天的价格往前看,假设自己在当天以前的最低点购买,利益是多少,如果当前点的收益比全局收益更大则更新全局收益。同时保存当前以前的全局最低点。遍历完成的时候,就可以得到最大的收益值
class Solution {
public:
int maxProfit(vector<int>& prices) {
int profit = 0; // 全局最大收益
int past_lowerest = prices[0]; // 历史最低点
for (auto it = prices.cbegin(); it != prices.cend(); ++it)
{
if (*it - past_lowerest > profit) // 更新全局收益的情况
profit = *it - past_lowerest;
if (*it < past_lowerest) // 更新历史最低点的情况
past_lowerest = *it;
}
return profit;
}
};
解法4:动态规划
这里动态规划的思路是,下一个状态只与前一个状态有关。如果当前值减掉历史最小值大于前一个状态,当前状态就设为当前值减掉历史最小值,否则当前状态就等于前一个状态
其状态转移方程为 ,又因为只与上一个状态有关,因此我们不需要维护整个数组来记录dp状态,只需要一个变量就可以。
class Solution {
public:
int maxProfit(vector<int>& prices) {
int lastlowest = prices[0];
int dp = 0;
for (size_t i = 1; i != prices.size(); ++i)
{
dp = prices[i] - lastlowest > dp ? prices[i] - lastlowest : dp;
if (prices[i] < lastlowest)
lastlowest = prices[i];
}
return dp;
}
};